溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

RPC框架有什么用

發布時間:2021-12-08 11:48:05 來源:億速云 閱讀:189 作者:iii 欄目:大數據

這篇文章主要講解了“RPC框架有什么用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“RPC框架有什么用”吧!

本地過程調用

RPC就是要像調用本地的函數一樣去調遠程函數。在研究RPC前,我們先看看本地調用是怎么調的。假設我們要調用函數Multiply來計算 lvalue * rvalue的結果:

int Multiply(int l, int r) 
{
    int y = l * r;
    return y;
}
 
int lvalue = 10;
int rvalue = 20;
int l_times_r = Multiply(lvalue, rvalue);

那么在第8行時,我們實際上執行了以下操作:

  1. 將 lvalue 和 rvalue 的值壓棧

  2. 進入Multiply函數,取出棧中的值10 和 20,將其賦予 l 和 r

  3. 執行第2行代碼,計算 l * r ,并將結果存在 y

  4. 將 y 的值壓棧,然后從Multiply返回

  5. 第8行,從棧中取出返回值 200 ,并賦值給 l_times_r

以上5步就是執行本地調用的過程。(20190116注:以上步驟只是為了說明原理。事實上編譯器經常會做優化,對于參數和返回值少的情況會直接將其存放在寄存器,而不需要壓棧彈棧的過程,甚至都不需要調用call,而直接做inline操作。僅就原理來說,這5步是沒有問題的。)
遠程過程調用帶來的新問題

在遠程調用時,我們需要執行的函數體是在遠程的機器上的,也就是說,Multiply是在另一個進程中執行的。這就帶來了幾個新問題:

  1. Call ID映射。我們怎么告訴遠程機器我們要調用Multiply,而不是Add或者FooBar呢?在本地調用中,函數體是直接通過函數指針來指定的,我們調用Multiply,編譯器就自動幫我們調用它相應的函數指針。但是在遠程調用中,函數指針是不行的,因為兩個進程的地址空間是完全不一樣的。所以,在RPC中,所有的函數都必須有自己的一個ID。這個ID在所有進程中都是唯一確定的??蛻舳嗽谧鲞h程過程調用時,必須附上這個ID。然后我們還需要在客戶端和服務端分別維護一個 {函數 <--> Call ID} 的對應表。兩者的表不一定需要完全相同,但相同的函數對應的Call ID必須相同。當客戶端需要進行遠程調用時,它就查一下這個表,找出相應的Call ID,然后把它傳給服務端,服務端也通過查表,來確定客戶端需要調用的函數,然后執行相應函數的代碼。

  2. 序列化和反序列化??蛻舳嗽趺窗褏抵祩鹘o遠程的函數呢?在本地調用中,我們只需要把參數壓到棧里,然后讓函數自己去棧里讀就行。但是在遠程過程調用時,客戶端跟服務端是不同的進程,不能通過內存來傳遞參數。甚至有時候客戶端和服務端使用的都不是同一種語言(比如服務端用C++,客戶端用Java或者Python)。這時候就需要客戶端把參數先轉成一個字節流,傳給服務端后,再把字節流轉成自己能讀取的格式。這個過程叫序列化和反序列化。同理,從服務端返回的值也需要序列化反序列化的過程。

  3. 網絡傳輸。遠程調用往往用在網絡上,客戶端和服務端是通過網絡連接的。所有的數據都需要通過網絡傳輸,因此就需要有一個網絡傳輸層。網絡傳輸層需要把Call ID和序列化后的參數字節流傳給服務端,然后再把序列化后的調用結果傳回客戶端。只要能完成這兩者的,都可以作為傳輸層使用。因此,它所使用的協議其實是不限的,能完成傳輸就行。盡管大部分RPC框架都使用TCP協議,但其實UDP也可以,而gRPC干脆就用了HTTP2。Java的Netty也屬于這層的東西。

有了這三個機制,就能實現RPC了,具體過程如下:

// Client端 
//    int l_times_r = Call(ServerAddr, Multiply, lvalue, rvalue)
1. 將這個調用映射為Call ID。這里假設用最簡單的字符串當Call ID的方法
2. 將Call ID,lvalue和rvalue序列化??梢灾苯訉⑺鼈兊闹狄远M制形式打包
3. 把2中得到的數據包發送給ServerAddr,這需要使用網絡傳輸層
4. 等待服務器返回結果
5. 如果服務器調用成功,那么就將結果反序列化,并賦給l_times_r

// Server端
1. 在本地維護一個Call ID到函數指針的映射call_id_map,可以用std::map<std::string, std::function<>>
2. 等待請求
3. 得到一個請求后,將其數據包反序列化,得到Call ID
4. 通過在call_id_map中查找,得到相應的函數指針
5. 將lvalue和rvalue反序列化后,在本地調用Multiply函數,得到結果
6. 將結果序列化后通過網絡返回給Client

所以要實現一個RPC框架,其實只需要按以上流程實現就基本完成了。

其中:

  • Call ID映射可以直接使用函數字符串,也可以使用整數ID。映射表一般就是一個哈希表。

  • 序列化反序列化可以自己寫,也可以使用Protobuf或者FlatBuffers之類的。

  • 網絡傳輸庫可以自己寫socket,或者用asio,ZeroMQ,Netty之類。

當然,這里面還有一些細節可以填充,比如如何處理網絡錯誤,如何防止攻擊,如何做流量控制,等等。但有了以上的架構,這些都可以持續加進去。

感謝各位的閱讀,以上就是“RPC框架有什么用”的內容了,經過本文的學習后,相信大家對RPC框架有什么用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

rpc
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女