溫馨提示×

溫馨提示×

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

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

RPC是什么?

發(fā)布時(shí)間:2020-06-24 08:06:00 來源:網(wǎng)絡(luò) 閱讀:550 作者:shaiberni 欄目:軟件技術(shù)

目錄
1、什么是RPC?
2、典型RPC調(diào)用框架
3、Thrift框架介紹
1、什么是RPC?
(1)RPC(remote procedure call):遠(yuǎn)程調(diào)用過程。

  服務(wù)器A部署應(yīng)用a,服務(wù)器B部署應(yīng)用b,當(dāng)A服務(wù)器調(diào)用B服務(wù)器上的b應(yīng)用的函數(shù)或者方法時(shí),因?yàn)椴辉谕粌?nèi)存空間,不能直接調(diào)用,必須通過網(wǎng)絡(luò)來表達(dá)調(diào)用的語義傳達(dá)調(diào)用的數(shù)據(jù)。

既然是調(diào)用B機(jī)器上的服務(wù),那A機(jī)器自己也創(chuàng)建一個(gè)這個(gè)服務(wù)不就也可以調(diào)用了么。原理上是可以這么做,但是隨著計(jì)算機(jī)的橫向發(fā)展,集群的出現(xiàn),使得多臺機(jī)器部署成一個(gè)集群來對外提供服務(wù)。無法在一個(gè)進(jìn)程內(nèi)甚至同一臺計(jì)算機(jī)上完成的需求就得需要RPC來實(shí)現(xiàn)了。

RPC的框架很多,比如最早的額CORBA,Java RMI,Web Service的RPC風(fēng)格,Hessian,Thrift,甚至是Rest API。

(2) 本地過程調(diào)用過程

   RPC就是要像調(diào)用本地的函數(shù)一樣去調(diào)遠(yuǎn)程函數(shù)。在研究RPC前,我們先看看本地調(diào)用是怎么調(diào)的。假設(shè)我們要調(diào)用函數(shù)Multiply來計(jì)算lvalue * rvalue的結(jié)果:

1 int Multiply(int l, int r) {

2 int y = l * r;

3 return y;

4 }

5

6 int lvalue = 10;

7 int rvalue = 20;

8 int l_times_r = Multiply(lvalue, rvalue);

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

將 lvalue 和 rvalue 的值壓棧

進(jìn)入Multiply函數(shù),取出棧中的值10 和 20,將其賦予 l 和 r

執(zhí)行第2行代碼,計(jì)算 l * r ,并將結(jié)果存在 y

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

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

  以上5步就是執(zhí)行本地調(diào)用的過程。

(3)遠(yuǎn)程過程調(diào)用帶來的新問題

 在遠(yuǎn)程調(diào)用時(shí),我們需要執(zhí)行的函數(shù)體是在遠(yuǎn)程的機(jī)器上的,也就是說,Multiply是在另一個(gè)進(jìn)程中執(zhí)行的。這就帶來了幾個(gè)新問題:

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

序列化和反序列化。客戶端怎么把參數(shù)值傳給遠(yuǎn)程的函數(shù)呢?在本地調(diào)用中,我們只需要把參數(shù)壓到棧里,然后讓函數(shù)自己去棧里讀就行。但是在遠(yuǎn)程過程調(diào)用時(shí),客戶端跟服務(wù)端是不同的進(jìn)程,不能通過內(nèi)存來傳遞參數(shù)。甚至有時(shí)候客戶端和服務(wù)端使用的都不是同一種語言(比如服務(wù)端用C++,客戶端用Java或者Python)。這時(shí)候就需要客戶端把參數(shù)先轉(zhuǎn)成一個(gè)字節(jié)流,傳給服務(wù)端后,再把字節(jié)流轉(zhuǎn)成自己能讀取的格式。這個(gè)過程叫序列化和反序列化。同理,從服務(wù)端返回的值也需要序列化反序列化的過程。

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

 所以,要實(shí)現(xiàn)一個(gè)RPC框架,其實(shí)只需要把以上三點(diǎn)實(shí)現(xiàn)了就基本完成了。

 Call ID映射可以直接使用函數(shù)字符串,也可以使用整數(shù)ID。映射表一般就是一個(gè)哈希表。

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

 網(wǎng)絡(luò)傳輸庫可以自己寫socket,或者用asio,ZeroMQ,Netty之類。

2、典型RPC調(diào)用框架

RPC的實(shí)現(xiàn)和調(diào)用框架很多,簡單介紹其中幾種比較典型的:

RMI(RemoteManagementInterface),利用java.rmi包實(shí)現(xiàn),基于Java遠(yuǎn)程方法協(xié)議(Java Remote Method Protocol) 和java的原生序列化。

Hessian,是一個(gè)輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能。 基于HTTP協(xié)議,采用二進(jìn)制編解碼。

protobuf-rpc-pro,是一個(gè)Java類庫,提供了基于 Google 的 Protocol Buffers 協(xié)議的遠(yuǎn)程方法調(diào)用的框架?;?Netty 底層的 NIO 技術(shù)。支持 TCP 重用/ keep-alive、SSL加密、RPC 調(diào)用取消操作、嵌入式日志等能。

Thrift,是一種可伸縮的跨語言服務(wù)的軟件框架。它擁有功能強(qiáng)大的代碼生成引擎,無縫地支持C + +,C#,Java,Python和PHP和Ruby。thrift允許你定義一個(gè)描述文件,描述數(shù)據(jù)類型和服務(wù)接口。依據(jù)該文件,編譯器方便地生成RPC客戶端和服務(wù)器通信代碼。最初由facebook開發(fā)用做系統(tǒng)內(nèi)個(gè)語言之間的RPC通信,2007年由facebook貢獻(xiàn)到apache基金 ,現(xiàn)在是apache下的opensource之一 。支持多種語言之間的RPC方式的通信:php語言client可以構(gòu)造一個(gè)對象,調(diào)用相應(yīng)的服務(wù)方法來調(diào)用java語言的服務(wù),跨越語言的C/S RPC調(diào)用。底層通訊基于SOCKET。

Avro,出自Hadoop之父Doug Cutting, 在Thrift已經(jīng)相當(dāng)流行的情況下推出Avro的目標(biāo)不僅是提供一套類似Thrift的通訊中間件,更是要建立一個(gè)新的,標(biāo)準(zhǔn)性的云計(jì)算的數(shù)據(jù)交換和存儲的Protocol。支持HTTP,TCP兩種協(xié)議。

3、Thrift框架介紹
最常見的RPC工具是Facebook開源的Thrift RPC框架。

Thrift是一個(gè)跨語言的服務(wù)部署框架,最初由Facebook于2007年開發(fā),2008年進(jìn)入Apache開源項(xiàng)目。Thrift通過一個(gè)中間語言(IDL, 接口定義語言)來定義RPC的接口和數(shù)據(jù)類型,然后通過一個(gè)編譯器生成不同語言的代碼(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代碼負(fù)責(zé)RPC協(xié)議層和傳輸層的實(shí)現(xiàn)。

Thrift實(shí)際上是實(shí)現(xiàn)了C/S模式,通過代碼生成工具將接口定義文件生成服務(wù)器端和客戶端代碼(可以為不同語言),從而實(shí)現(xiàn)服務(wù)端和客戶端跨語言的支持。用戶在Thirft描述文件中聲明自己的服務(wù),這些服務(wù)經(jīng)過編譯后會生成相應(yīng)語言的代碼文件,然后用戶實(shí)現(xiàn)服務(wù)(客戶端調(diào)用服務(wù),服務(wù)器端提服務(wù))便可以了。其中protocol(協(xié)議層, 定義數(shù)據(jù)傳輸格式,可以為二進(jìn)制或者XML等)和transport(傳輸層,定義數(shù)據(jù)傳輸方式,可以為TCP/IP傳輸,內(nèi)存共享或者文件共享等)被用作運(yùn)行時(shí)庫。

Thrift的協(xié)議棧如下圖所示:

重試

在Client和Server的最頂層都是用戶自定義的處理邏輯,也就是說用戶只需要編寫用戶邏輯,就可以完成整套的RPC調(diào)用流程。用戶邏輯的下一層是Thrift自動生成的代碼,這些代碼主要用于結(jié)構(gòu)化數(shù)據(jù)的解析,發(fā)送和接收,同時(shí)服務(wù)器端的自動生成代碼中還包含了RPC請求的轉(zhuǎn)發(fā)(Client的A調(diào)用轉(zhuǎn)發(fā)到Server A函數(shù)進(jìn)行處理)。

協(xié)議棧的其他模塊都是Thrift的運(yùn)行時(shí)模塊:

底層IO模塊,負(fù)責(zé)實(shí)際的數(shù)據(jù)傳輸,包括Socket,文件,或者壓縮數(shù)據(jù)流等。

TTransport負(fù)責(zé)以字節(jié)流方式發(fā)送和接收Message,是底層IO模塊在Thrift框架中的實(shí)現(xiàn),每一個(gè)底層IO模塊都會有一個(gè)對應(yīng)TTransport來負(fù)責(zé)Thrift的字節(jié)流(Byte Stream)數(shù)據(jù)在該IO模塊上的傳輸。例如TSocket對應(yīng)Socket傳輸,TFileTransport對應(yīng)文件傳輸。

TProtocol主要負(fù)責(zé)結(jié)構(gòu)化數(shù)據(jù)組裝成Message,或者從Message結(jié)構(gòu)中讀出結(jié)構(gòu)化數(shù)據(jù)。TProtocol將一個(gè)有類型的數(shù)據(jù)轉(zhuǎn)化為字節(jié)流以交給TTransport進(jìn)行傳輸,或者從TTransport中讀取一定長度的字節(jié)數(shù)據(jù)轉(zhuǎn)化為特定類型的數(shù)據(jù)。如int32會被TBinaryProtocol Encode為一個(gè)四字節(jié)的字節(jié)數(shù)據(jù),或者TBinaryProtocol從TTransport中取出四個(gè)字節(jié)的數(shù)據(jù)Decode為int32。

TServer負(fù)責(zé)接收Client的請求,并將請求轉(zhuǎn)發(fā)到Processor進(jìn)行處理。TServer主要任務(wù)就是高效的接受Client的請求,特別是在高并發(fā)請求的情況下快速完成請求。

Processor(或者TProcessor)負(fù)責(zé)對Client的請求做出相應(yīng),包括RPC請求轉(zhuǎn)發(fā),調(diào)用參數(shù)解析和用戶邏輯調(diào)用,返回值寫回等處理步驟。Processor是服務(wù)器端從Thrift框架轉(zhuǎn)入用戶邏輯的關(guān)鍵流程。Processor同時(shí)也負(fù)責(zé)向Message結(jié)構(gòu)中寫入數(shù)據(jù)或者讀出數(shù)據(jù)。

Thrift的模塊設(shè)計(jì)非常好,在每一個(gè)層次都可以根據(jù)自己的需要選擇合適的實(shí)現(xiàn)方式。同時(shí)也應(yīng)該注意到Thrift目前的特性并不是在所有的程序語言中都支持。例如C++實(shí)現(xiàn)中有TDenseProtocol沒有TTupleProtocol,而Java實(shí)現(xiàn)中有TTupleProtocol沒有TDenseProtocol。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI