RPC框架淺析

RPC框架

之前在應用微服務時,發現Spring Cloud中各服務之間的調用走的是http,如果一個請求調用鏈路過多,則會導致時間較長,所以近期調研了RPC框架,看能否應用到系統中。

1、什麼是RPC

首先要了解什麼是RPC,先了解一個概念是IPC,進程間通信(IPC,Inter-Process Communication),指至少兩個進程或線程間傳送數據或信號的一些技術或方法。進程是計算機系統分配資源的最小單位。每個進程都有自己的一部分獨立的系統資源,彼此是隔離的。爲了能使不同的進程互相訪問資源並進行協調工作,纔有了進程間通信。這些進程可以運行在同一計算機上或網絡連接的不同計算機上。 進程間通信技術包括消息傳遞、同步、共享內存和遠程過程調用。 IPC是一種標準的Unix通信機制。

IPC分兩種:

  • 本地過程調用(LPC),LPC用在多任務操作系統中,使得同時運行的任務能互相會話。這些任務共享內存空間使任務同步和互相發送信息。
  • 遠程過程調用(RPC)RPC類似於LPC,只是在網上工作。RPC開始是出現在Sun微系統公司和HP公司的運行UNIX操作系統的計算機中。

2、和RESTful API的區別

RPC經常用來比較的是RESTful API,也是日常在後臺接口開發中常用的一種模式,定義了一種前後端交互的規範。

RESTful API是Representational State Transfer的縮寫。直接翻譯的意思是"表現層狀態轉化"。
它是一種互聯網應用程序的API設計理念:URL定位資源,用HTTP動詞(GET,POST,DELETE,DETC)描述操作。之前的文章中分析過RestfulAPI,這是一種api的設計原則和指導規範,是一種接口設計理念,好處是松耦合。

我的理解是,RESTful API和RPC概念上不是一種東西,不能用來比較。但從設計理念上,RestfulAPI是松耦合,將函數映射爲API,但RPC傾向於緊密耦合。RPC客戶端以多種方式與服務實現緊密耦合,並且很難在不中斷客戶端的情況下更改服務實現。所以從場景上說,RESTful API更多地用於外部調用,RPC更多用於複雜系統內部調用。

3、RPC實現原理

img

1、建立通信

首先要解決通訊的問題:即A機器想要調用B機器,首先得建立起通信連接。主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調用的所有相關的數據都在這個連接裏面進行傳輸交換。

通常這個連接可以是按需連接(需要調用的時候就先建立連接,調用結束後就立馬斷掉),也可以是長連接(客戶端和服務器建立起連接之後保持長期持有,不管此時有無數據包的發送,可以配合心跳檢測機制定期檢測建立的連接是否存活有效),多個遠程過程調用共享同一個連接。

2、服務尋址

解決尋址的問題:即A機器上的應用A要調用B機器上的應用B,那麼此時對於A來說如何告知底層的RPC框架所要調用的服務具體在哪裏呢?

通常情況下我們需要提供B機器(主機名或IP地址)以及特定的端口,然後指定調用的方法或者函數的名稱以及入參出參等信息,這樣才能完成服務的一個調用。比如基於Web服務協議棧的RPC,就需要提供一個endpoint URI,或者是從UDDI服務上進行查找。如果是RMI調用的話,還需要一個RMI Registry來註冊服務的地址。

3、網絡傳輸

3.1、序列化

當A機器上的應用發起一個RPC調用時,調用方法和其入參等信息需要通過底層的網絡協議如TCP傳輸到B機器,由於網絡協議是基於二進制的,所有我們傳輸的參數數據都需要先進行序列化(Serialize)或者編組(marshal)成二進制的形式才能在網絡中進行傳輸。然後通過尋址操作和網絡傳輸將序列化或者編組之後的二進制數據發送給B機器。

3.2、反序列化

當B機器接收到A機器的應用發來的請求之後,又需要對接收到的參數等信息進行反序列化操作(序列化的逆操作),即將二進制信息恢復爲內存中的表達方式,然後再找到對應的方法(尋址的一部分)進行本地調用(一般是通過生成代理Proxy去調用, 通常會有JDK動態代理、CGLIB動態代理、Javassist生成字節碼技術等),之後得到調用的返回值。

4、服務調用

B機器進行本地調用(通過代理Proxy)之後得到了返回值,此時還需要再把返回值發送回A機器,同樣也需要經過序列化操作,然後再經過網絡傳輸將二進制數據發送回A機器,而當A機器接收到這些返回值之後,則再次進行反序列化操作,恢復爲內存中的表達方式,最後再交給A機器上的應用進行相關處理(一般是業務邏輯處理操作)。

4、RPC通信過程

1、RPC架構包含的組件

1、客戶端(Client):服務調用方(服務消費者)
2、客戶端存根(Client Stub):存放服務端地址信息,將客戶端的請求參數數據信息打包成網絡消息,再通過網絡傳輸發送給服務端
3、服務端存根(Server Stub):接收客戶端發送過來的請求消息並進行解包,然後再調用本地服務進行處理
4、服務端(Server):服務的真正提供者

2、具體調用過程

1、服務消費者(client客戶端)通過本地調用的方式調用服務
2、客戶端存根(client stub)接收到調用請求後負責將方法、入參等信息序列化(組裝)成能夠進行網絡傳輸的消息體
3、客戶端存根(client stub)找到遠程的服務地址,並且將消息通過網絡發送給服務端
4、服務端存根(server stub)收到消息後進行解碼(反序列化操作)
5、服務端存根(server stub)根據解碼結果調用本地的服務進行相關處理
6、本地服務執行具體業務邏輯並將處理結果返回給服務端存根(server stub)
7、服務端存根(server stub)將返回結果重新打包成消息(序列化)並通過網絡發送至消費方
8、客戶端存根(client stub)接收到消息,並進行解碼(反序列化)
9、服務消費方得到最終結果

5、跨語言RPC框架

  • gRPC:Google 於 2015 年對外開源的跨語言 RPC 框架,支持多種語言。
  • Thrift:最初是由 Facebook 開發的內部系統跨語言的 RPC 框架,2007 年貢獻給了 Apache 基金,成爲 Apache 開源項目之一,支持多種語言。

6、JAVA RPC框架

  • Dubbo:國內最早開源的 RPC 框架,由阿里巴巴公司開發並於 2011 年末對外開源,僅支持 Java 語言。
  • Motan:微博內部使用的 RPC 框架,於 2016 年對外開源,僅支持 Java 語言。
  • Tars:騰訊內部使用的 RPC 框架,於 2017 年對外開源,僅支持 C++ 語言。
  • RMI:利用java.rmi包實現,基於Java遠程方法協議(Java Remote Method Protocol) 和java的原生序列化。
  • protobuf-rpc-pro:提供了基於 Google 的 Protocol Buffers 協議的遠程方法調用的框架。基於 Netty 底層的 NIO 技術。支持 TCP 重用/ keep-alive、SSL加密、RPC 調用取消操作、嵌入式日誌等功能。

7、實現技術

從上面的RPC調用過程可以看出,在這個實現過程中,用到了以下技術:

  • 動態代理
  • 序列化和反序列化
  • NIO通信
  • 服務註冊發現

大致瞭解了RPC是什麼、RPC的基本原理,後面會在項目中使用,並會嘗試自己實現一個RPC框架來學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章