04.16 RPC框架的原理和應用方法

隨著集中式架構向分佈式架構的轉變,應用系統之間的服務調用與通訊問題成為了首要解決的需求。而RPC 的主要目標就是為了讓構建分佈式計算(應用)變得更加簡單,在提供強大的遠程調用能力時不損失本地調用的語義簡潔性。 為實現該目標,RPC 框架需提供一種透明調用機制讓使用者不必顯式的區分本地調用和遠程調用。

RPC 即Remote Procedure Call 是一種進程間通信方式。 RPC的作用主要有三個方面:進程間通訊、提供和本地方法調用一樣的調用機制、屏蔽程序員對遠程調用的細節實現。

首先是進程間的通信問題,對於分佈式環境,rpc能夠幫助我們解決不同服務器之間的通信及數據傳輸問題,即做好方法調用到數據的轉換,然後藉助網絡進行數據傳遞;rpc客戶端向rpc服務端發起遠程服務調用,通過請求的封裝,參數的封裝,序列化、編碼、約定協議傳輸、解析請求、處理請求、封裝返回消息數據、在進行返回數據的序列化、編碼、在通過網絡返回給客戶端。再者是提供和本地方法調用一樣的調用機制,尚學堂•百戰程序員陳老師指出,對於業務系統來說,我們更多的關注點在於如何解決實際的業務需求問題,而不想花更多的時間和心思在諸如上述過程中關於網絡傳輸及編解碼過程,因此對於rpc來說,需要將這些編解碼、協議約定、網絡傳輸等進行一個整體的封裝,然後只向業務系統提供最簡單的調用方式。最後一個屏蔽程序員對遠程調用的細節實現,其實也就是第二點中提到的那些功能的封裝,我們不用去關係rpc到底是如何實現的,也不用關心它是如何運作的,對於業務開發人員來說,通過約定的方式進行類似於本地方法調用的形式來調用遠程服務接口就可以了。

那麼如何實現透明化的遠程調用呢?

什麼樣的內部封裝才能讓我們覺得像以本地調用方式調用遠程服務呢?

對於java來說就是使用代理。java代理有兩種方式:1) jdk 動態代理(接口代理);2)cglib代理(子類代理)。儘管字節碼生成方式實現的代理更為強大和高效,但代碼不易維護,大部分公司實現RPC框架時還是選擇動態代理方式。這部分也將會在後續的章節中展開來說。

RPC框架的原理和應用方法

從發起遠程調用到接收到數據返回結果,大致過程是:

1)服務消費方(client)調用以本地調用方式調用服務;

2)client stub接收到調用後負責將方法、參數等組裝成能夠進行網絡傳輸的消息體;

3)client stub找到服務地址,並將消息發送到服務端;

4)server stub收到消息後進行解碼;

5)server stub根據解碼結果調用本地的服務;

6)本地服務執行並將結果返回給server stub;

7)server stub將返回結果打包成消息併發送至消費方;

8)client stub接收到消息,並進行解碼;

9)服務消費方得到最終結果。

那麼rpc就相當於將step2-step8的步驟進行了封裝。下面借用一張網上的圖片來幫助我們理解這個過程。

RPC 服務端通過 RpcServer 去暴露服務接口,而客戶端通過 RpcClient 去獲取服務接口。客戶端像調用本地方法一樣去調用遠程接口方法,RPC 框架提供接口的代理實現,實際的調用將委託給代理 RpcProxy。代理封裝調用信息並將調用轉交給 RpcInvoker 去實際執行。在客戶端的 RpcInvoker 通過連接器 RpcConnector 去維持與服務端的通道 RpcChannel,並使用 RpcProtocol 執行協議編碼(encode)並將編碼後的請求消息通過通道發送給服務端。RPC 服務端接收器 RpcAcceptor接收客戶端的調用請求,同樣使用 RpcProtocol 執行協議解碼(decode)。

解碼後的調用信息傳遞給 RpcProcessor 去控制處理調用過程,最後再委託調用給 RpcInvoker 去實際執行並返回調用結果。

通過上述分析可知,這裡麵包括以下核心組件:

用於暴露服務接口的RpcServer

用於發現服務接口的RpcClient

遠程接口的代理實現RpcProxy

負責協議編解碼的RpcProtocol(實際的rpc框架中一般會提供多種不同的實現)

常用的分佈式RPC框架有:dubbo、motan、rpcx、gRPC、thrift等等。

關於常見的RPC框架也做了基本認識,對於這些優秀的框架,我們在實現我們自己RPC時可以借鑑一下這些架構裡的一些模式以及技術。最後說明了下為什麼我們會在分佈式架構中要使用RPC而不是MQ,對於MQ來說,在處理同步調用無法滿足實際的生產需求,而RPC才更加適合分佈式應用的實際需要。

RPC框架的原理和應用方法


分享到:


相關文章: