RPC接口測試(六)RPC協議解析(重要!重要!重要!)


RPC協議解析

RPC(Remote Procedure Call Protocol)遠程過程調用協議,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。簡言之,RPC使得程序能夠像訪問本地系統資源一樣,去訪問遠端系統資源。比較關鍵的一些方面包括:通訊協議、序列化、資源(接口)描述、服務框架、性能、語言支持等,注冊中心一般為ZooKeeper

 

 

 

簡單的說,RPC就是從一台機器(客戶端)上通過參數傳遞的方式調用另一台機器(服務器)上的一個函數或方法(可以統稱為服務)並得到返回的結果。

三、RPC架構組件

一個基本的RPC架構里面應該至少包含以下4個組件:

1、客戶端(Client):

服務調用方(服務消費者)

2、客戶端存根(Client Stub):

存放服務端地址信息,將客戶端的請求參數數據信息打包成網絡消息,再通過網絡傳輸發送給服務端

3、服務端存根(Server Stub):

接收客戶端發送過來的請求消息並進行解包,然后再調用本地服務進行處理

4、服務端(Server):

服務的真正提供者

 

 

 

具體調用過程:

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框架的實現目標則是將上面的第2-10步完好地封裝起來,也就是把調用、編碼/解碼的過程給封裝起來,讓用戶感覺上像調用本地服務一樣的調用遠程服務。

RPC協議基本原理

也就是說兩台服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的函數/方法,由於不在一個內存空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的數據。

比如說,A 服務器想調用 B 服務器上User模塊的一個方法getUserByName

User user = new User();

user.getUserByName(String userName);

就像在A 服務本地創建對象一樣操作B服務里面的User模塊

1、建立通信

首先要解決通訊的問題:即A機器想要調用B機器,首先得建立起通信連接。

主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調用的所有交換的數據都在這個連接里傳輸。連接可以是按需連接,調用結束后就斷掉,也可以是長連接,多個遠程過程調用共享同一個連接。

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

2、服務尋址

要解決尋址的問題,也就是說,A服務器上的應用怎么告訴底層的RPC框架,如何連接到B服務器(如主機或IP地址)以及特定的端口,方法的名稱名稱是什么。

通常情況下我們需要提供B機器(主機名或IP地址)以及特定的端口,然后指定調用的方法或者函數的名稱以及入參出參等信息,這樣才能完成服務的一個調用。

可靠的尋址方式(主要是提供服務的發現)是RPC的實現基石,比如可以采用Redis或者Zookeeper來注冊服務等等。

2.1、從服務提供者的角度看:

2.1.1、當服務提供者啟動的時候,需要將自己提供的服務注冊到指定的注冊中心,以便服務消費者能夠通過服務注冊中心進行查找;

2.1.2、當服務提供者由於各種原因致使提供的服務停止時,需要向注冊中心注銷停止的服務;

2.1.3、服務的提供者需要定期向服務注冊中心發送心跳檢測,服務注冊中心如果一段時間未收到來自服務提供者的心跳后,認為該服務提供者已經停止服務,則將該服務從注冊中心上去掉

2.2、從調用者的角度看:

2.2.1、服務的調用者啟動的時候根據自己訂閱的服務向服務注冊中心查找服務提供者的地址等信息;

2.2.2、當服務調用者消費的服務上線或者下線的時候,注冊中心會告知該服務的調用者;

2.2.3、服務調用者下線的時候,則取消訂閱。

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機器上的應用進行相關處理,一般是業務邏輯處理操作。

通常,經過以上四個步驟之后,一次完整的RPC調用算是完成了,另外可能因為網絡抖動等原因需要重試等。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM