詳解RPC框架實現原理

RPC是什麼?爲什麼要使用RPC?開源的RPC框架有哪些?它有什麼優勢?基於TCP和HTTP協議的RPC調用有什麼不同?......帶着這些疑問,我們逐個解答🤞。

1. 背景

  • 隨着企業IT服務的不斷髮展,單臺服務器逐漸無法承受用戶日益增長的請求壓力時,就需要多臺服務器聯合起來構成「服務集羣」共同對外提供服務。

  • 同時業務服務會隨着產品需求的增多越來越腫,架構上必須進行服務拆分,一個完整的大型服務會被打散成很多很多獨立的小服務,每個小服務會由獨立的進程去管理來對外提供服務,這就是「微服務」。

  • 當用戶的請求到來時,我們需要將用戶的請求分散到多個服務去各自處理,然後又需要將這些子服務的結果彙總起來呈現給用戶。那麼服務之間該使用何種方式進行交互就是需要解決的核心問題。RPC就是爲解決服務之間信息交互而發明和存在的。

2. 什麼是RPC?

RPCRemote Procedure Call)即遠程過程調用,是分佈式系統常見的一種通信方法。允許程序調用另一個地址空間(通常是共享網絡的另一臺機器上)的過程或函數,而不用程序員顯式編碼這個遠程調用的細節。

什麼玩意呢?簡單地說,A使用HTTP或者Socket通信協議,通過參數傳遞遠程調用B提供的服務,並得到返回的結果,這麼一個調用過程稱之爲RPC。

3. RPC框架有哪些?

  • Dubbo:國內最早開源的RPC框架,由阿里巴巴公司開發並對外開源,僅支持Java語言。
  • Dubbox:是噹噹團隊基於Dubbox升級的一個版本。是一個分佈式的服務架構,可直接用於生產環境作爲SOA服務框架。
  • gRPC:是Google開發的高性能、通用的開源RPC框架,支持多種語言。
  • Thrift:最初是由Facebook開發的內部系統跨語言的RPC框架,支持多種語言。
  • Motan:微博內部使用的RPC框架,僅支持Java語言。
  • Tars:騰訊內部使用的RPC框架,支持C++、Java、Nodejs、Php、Go等語言。
  • Spring Cloud:國外Pivotal公司2014年對外開源的RPC框架,僅支持Java語言
  • Hprose:一個MIT開源許可的新型輕量級跨語言跨平臺的面向對象的高性能遠程動態通訊中間件,它支持衆多語言。

4. 爲什麼要使用RPC?

在一個典型RPC的使用場景中,包含了服務發現、負載、容錯、網絡傳輸、序列化等組件,而RPC的主要目標是更容易地構建分佈式應用。爲實現該目標,RPC框架需提供一種透明調用機制,讓使用者不必顯式的區分本地調用和遠程調用。

5. RPC架構重要組成

5.1 服務尋址

服務尋址可以使用Call ID映射。在本地調用中,函數體是直接通過函數指針來指定的,但是在遠程調用中,函數指針是不行的,因爲兩個進程的地址空間是完全不一樣的。所以在RPC中,所有的函數都必須有自己的一個 ID並且唯一。客戶端在做遠程過程調用時,必須附上這個ID。然後我們還需要在客戶端和服務端分別維護一個函數和Call ID的對應表。當客戶端需要進行遠程調用時,它就查一下這個表,找出相應的Call ID,然後把它傳給服務端,服務端也通過查表,來確定客戶端需要調用的函數,然後執行相應函數的代碼。(映射表一般就是一個哈希表。

要調用服務,首先你需要一個服務註冊中心去查詢對方服務都有哪些實例。Dubbo的服務註冊中心是可以配置的,官方推薦使用Zookeeper。

5.2 序列化和反序列化

客戶端怎麼把參數值傳給遠程的函數呢?在本地調用中,我們只需要把參數壓到棧裏,然後讓函數自己去棧裏讀就行。但是在遠程過程調用時,客戶端跟服務端是不同的進程,不能通過內存來傳遞參數。這時候就需要客戶端把參數先轉成一個字節流,傳給服務端後,再把字節流轉成自己能讀取的格式。

只有二進制數據才能在網絡中傳輸,可以使用Protobuf或者FlatBuffers進行序列化和反序列化。

序列化和反序列化的定義是:

  • 將對象轉換成二進制流的過程叫做序列化。
  • 將二進制流轉換成對象的過程叫做反序列化。

5.3 網絡傳輸

所有的數據都需要通過網絡傳輸,因此就需要有一個網絡傳輸層。網絡傳輸層需要把Call ID和序列化後的參數字節流傳給服務端,然後再把序列化後的調用結果傳回客戶端。只要能完成這兩者的,都可以作爲傳輸層使用。因此,它所使用的協議其實是不限的,能完成傳輸就行。

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

6 基於不同協議的RPC調用

6.1 TCP協議

由服務的調用方與服務的提供方建立Socket連接,並由服務的調用方通過Socket將需要調用的接口名稱、方法名稱和參數序列化後傳遞給服務的提供方,服務的提供方反序列化後再利用反射調用相關的方法。

最後將結果返回給服務的調用方,整個基於TCP協議的RPC調用大致如此。但是在實例應用中則會進行一系列的封裝,如RMI便是在TCP協議上傳遞可序列化的Java對象。

6.2 HTTP協議

由服務的調用者向服務的提供者發送請求,這種請求的方式可能是GETPOSTPUTDELETE等中的一種,服務的提供者可能會根據不同的請求方式做出不同的處理,或者某個方法只允許某種請求方式。

而調用的具體方法則是根據URL進行方法調用,而方法所需要的參數可能是對服務調用方傳輸過去的XML數據或者JSON數據解析後的結果,最後返回JOSN或者XML的數據結果。

6.3 兩種方式的對比

  • 基於TCP的協議實現的RPC調用,由於TCP協議處於協議棧的下層,能夠更加靈活地對協議字段進行定製,減少網絡開銷,提高性能,實現更大的吞吐量和併發數。但是需要更多關注底層複雜的細節,實現的代價更高。

  • 基於HTTP協議實現的RPC則可以使用JSONXML格式的請求或響應數據。由於HTTP協議是上層協議,發送包含同等內容的信息,因此使用 HTTP協議傳輸所佔用的字節數會比使用TCP協議傳輸所佔用的字節數更高。

因此在同等網絡下,通過HTTP協議傳輸相同內容,效率會比基於TCP協議的數據效率要低,信息傳輸所佔用的時間也會更長,當然壓縮數據,能夠縮小這一差距。

通信框架:MINA和Netty。
遠程通信協議:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。

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