自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

花了一個星期,我終于把RPC框架整明白了!

原創(chuàng)
開發(fā) 架構(gòu) 開發(fā)工具
RPC(Remote Procedure Call):遠(yuǎn)程過程調(diào)用,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計算機程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的思想。

【51CTO.com原創(chuàng)稿件】RPC(Remote Procedure Call):遠(yuǎn)程過程調(diào)用,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計算機程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的思想。

RPC 是一種技術(shù)思想而非一種規(guī)范或協(xié)議,常見 RPC 技術(shù)和框架有:

  • 應(yīng)用級的服務(wù)框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。
  • 遠(yuǎn)程通信協(xié)議:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
  • 通信框架:MINA 和 Netty。

目前流行的開源 RPC 框架還是比較多的,有阿里巴巴的 Dubbo、Facebook 的 Thrift、Google 的 gRPC、Twitter 的 Finagle 等。

下面重點介紹三種:

  • gRPC:是 Google 公布的開源軟件,基于***的 HTTP 2.0 協(xié)議,并支持常見的眾多編程語言。RPC 框架是基于 HTTP 協(xié)議實現(xiàn)的,底層使用到了 Netty 框架的支持。
  • Thrift:是 Facebook 的開源 RPC 框架,主要是一個跨語言的服務(wù)開發(fā)框架。

用戶只要在其之上進(jìn)行二次開發(fā)就行,應(yīng)用對于底層的 RPC 通訊等都是透明的。不過這個對于用戶來說需要學(xué)習(xí)特定領(lǐng)域語言這個特性,還是有一定成本的。

  • Dubbo:是阿里集團(tuán)開源的一個極為出名的 RPC 框架,在很多互聯(lián)網(wǎng)公司和企業(yè)應(yīng)用中廣泛使用。協(xié)議和序列化框架都可以插拔是極其鮮明的特色。

完整的 RPC 框架

在一個典型 RPC 的使用場景中,包含了服務(wù)發(fā)現(xiàn)、負(fù)載、容錯、網(wǎng)絡(luò)傳輸、序列化等組件,其中“RPC 協(xié)議”就指明了程序如何進(jìn)行網(wǎng)絡(luò)傳輸和序列化。

 

圖 1:完整 RPC 架構(gòu)圖

如下是 Dubbo 的設(shè)計架構(gòu)圖,分層清晰,功能復(fù)雜:

 

圖 2:Dubbo 架構(gòu)圖

[[268129]] 

RPC 核心功能

RPC 的核心功能是指實現(xiàn)一個 RPC 最重要的功能模塊,就是上圖中的”RPC 協(xié)議”部分:

 

圖 3:RPC 核心功能

一個 RPC 的核心功能主要有 5 個部分組成,分別是:客戶端、客戶端 Stub、網(wǎng)絡(luò)傳輸模塊、服務(wù)端 Stub、服務(wù)端等。

 

圖 4:RPC 核心功能圖

下面分別介紹核心 RPC 框架的重要組成:

  • 客戶端(Client):服務(wù)調(diào)用方。
  • 客戶端存根(Client Stub):存放服務(wù)端地址信息,將客戶端的請求參數(shù)數(shù)據(jù)信息打包成網(wǎng)絡(luò)消息,再通過網(wǎng)絡(luò)傳輸發(fā)送給服務(wù)端。
  • 服務(wù)端存根(Server Stub):接收客戶端發(fā)送過來的請求消息并進(jìn)行解包,然后再調(diào)用本地服務(wù)進(jìn)行處理。
  • 服務(wù)端(Server):服務(wù)的真正提供者。
  • Network Service:底層傳輸,可以是 TCP 或 HTTP。

Python 自帶 RPC Demo

Server.py:

  1. from SimpleXMLRPCServer import SimpleXMLRPCServer    
  2. def fun_add(a,b): 
  3.     totle = a + b  
  4.     return totle 
  5. if __name__ == '__main__'
  6.     s = SimpleXMLRPCServer(('0.0.0.0', 8080))   #開啟xmlrpcserver 
  7.     s.register_function(fun_add)                #注冊函數(shù)fun_add 
  8.     print "server is online..." 
  9.     s.serve_forever()                           #開啟循環(huán)等待 

Client.py:

  1. from xmlrpclib import ServerProxy            #導(dǎo)入xmlrpclib的包 
  2. s = ServerProxy("http://172.171.5.205:8080") #定義xmlrpc客戶端 
  3. print s.fun_add(2,3)         

開啟服務(wù)端:

 

開啟客戶端:

 

Wireshark 抓包分析過程

客戶端去往服務(wù)端:

  • 客戶端 IP:172.171.4.176
  • 服務(wù)端 IP:172.171.5.95

通信使用 HTTP 協(xié)議,XML 文件傳輸格式。傳輸?shù)淖侄伟ǎ悍椒?methodName,兩個參數(shù) 2,3。

 

圖 5:Request 抓包

服務(wù)端返回結(jié)果,字段返回值 Value,結(jié)果是 5:

 

圖 6:Response 抓包

在這兩次網(wǎng)絡(luò)傳輸中使用了 HTTP 協(xié)議,建立 HTTP 協(xié)議之間有 TCP 三次握手,斷開 HTTP 協(xié)議時有 TCP 四次揮手。

 

圖 7:基于 HTTP 協(xié)議的 RPC 連接過程

詳細(xì)調(diào)用過程

Python 自帶 RPC 的 Demo 小程序的實現(xiàn)過程,流程和分工角色可以用下圖來表示:

 

圖 8:RPC 調(diào)用詳細(xì)流程圖

一次 RPC 調(diào)用流程如下:

  • 服務(wù)消費者(Client 客戶端)通過本地調(diào)用的方式調(diào)用服務(wù)。
  • 客戶端存根(Client Stub)接收到調(diào)用請求后負(fù)責(zé)將方法、入?yún)⒌刃畔⑿蛄谢?組裝)成能夠進(jìn)行網(wǎng)絡(luò)傳輸?shù)南Ⅲw。
  • 客戶端存根(Client Stub)找到遠(yuǎn)程的服務(wù)地址,并且將消息通過網(wǎng)絡(luò)發(fā)送給服務(wù)端。
  • 服務(wù)端存根(Server Stub)收到消息后進(jìn)行解碼(反序列化操作)。
  • 服務(wù)端存根(Server Stub)根據(jù)解碼結(jié)果調(diào)用本地的服務(wù)進(jìn)行相關(guān)處理
  • 服務(wù)端(Server)本地服務(wù)業(yè)務(wù)處理。
  • 處理結(jié)果返回給服務(wù)端存根(Server Stub)。
  • 服務(wù)端存根(Server Stub)序列化結(jié)果。
  • 服務(wù)端存根(Server Stub)將結(jié)果通過網(wǎng)絡(luò)發(fā)送至消費方。
  • 客戶端存根(Client Stub)接收到消息,并進(jìn)行解碼(反序列化)。
  • 服務(wù)消費方得到最終結(jié)果。

[[268131]] 

RPC 核心之功能實現(xiàn)

RPC 的核心功能主要由 5 個模塊組成,如果想要自己實現(xiàn)一個 RPC,最簡單的方式要實現(xiàn)三個技術(shù)點,分別是:

  • 服務(wù)尋址
  • 數(shù)據(jù)流的序列化和反序列化
  • 網(wǎng)絡(luò)傳輸

服務(wù)尋址

服務(wù)尋址可以使用 Call ID 映射。在本地調(diào)用中,函數(shù)體是直接通過函數(shù)指針來指定的,但是在遠(yuǎn)程調(diào)用中,函數(shù)指針是不行的,因為兩個進(jìn)程的地址空間是完全不一樣的。

所以在 RPC 中,所有的函數(shù)都必須有自己的一個 ID。這個 ID 在所有進(jìn)程中都是唯一確定的。

客戶端在做遠(yuǎn)程過程調(diào)用時,必須附上這個 ID。然后我們還需要在客戶端和服務(wù)端分別維護(hù)一個函數(shù)和Call ID的對應(yīng)表。

當(dāng)客戶端需要進(jìn)行遠(yuǎn)程調(diào)用時,它就查一下這個表,找出相應(yīng)的 Call ID,然后把它傳給服務(wù)端,服務(wù)端也通過查表,來確定客戶端需要調(diào)用的函數(shù),然后執(zhí)行相應(yīng)函數(shù)的代碼。

實現(xiàn)方式:服務(wù)注冊中心。

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

實現(xiàn)案例:RMI(Remote Method Invocation,遠(yuǎn)程方法調(diào)用)也就是 RPC 本身的實現(xiàn)方式。

 

圖 9:RMI 架構(gòu)圖

Registry(服務(wù)發(fā)現(xiàn)):借助 JNDI 發(fā)布并調(diào)用了 RMI 服務(wù)。實際上,JNDI 就是一個注冊表,服務(wù)端將服務(wù)對象放入到注冊表中,客戶端從注冊表中獲取服務(wù)對象。

RMI 服務(wù)在服務(wù)端實現(xiàn)之后需要注冊到 RMI Server 上,然后客戶端從指定的 RMI 地址上 Lookup 服務(wù),調(diào)用該服務(wù)對應(yīng)的方法即可完成遠(yuǎn)程方法調(diào)用。

Registry 是個很重要的功能,當(dāng)服務(wù)端開發(fā)完服務(wù)之后,要對外暴露,如果沒有服務(wù)注冊,則客戶端是無從調(diào)用的,即使服務(wù)端的服務(wù)就在那里。

序列化和反序列化

客戶端怎么把參數(shù)值傳給遠(yuǎn)程的函數(shù)呢?在本地調(diào)用中,我們只需要把參數(shù)壓到棧里,然后讓函數(shù)自己去棧里讀就行。

但是在遠(yuǎn)程過程調(diào)用時,客戶端跟服務(wù)端是不同的進(jìn)程,不能通過內(nèi)存來傳遞參數(shù)。

這時候就需要客戶端把參數(shù)先轉(zhuǎn)成一個字節(jié)流,傳給服務(wù)端后,再把字節(jié)流轉(zhuǎn)成自己能讀取的格式。

只有二進(jìn)制數(shù)據(jù)才能在網(wǎng)絡(luò)中傳輸,序列化和反序列化的定義是:

  • 將對象轉(zhuǎn)換成二進(jìn)制流的過程叫做序列化
  • 將二進(jìn)制流轉(zhuǎn)換成對象的過程叫做反序列化

這個過程叫序列化和反序列化。同理,從服務(wù)端返回的值也需要序列化反序列化的過程。

網(wǎng)絡(luò)傳輸

網(wǎng)絡(luò)傳輸:遠(yuǎn)程調(diào)用往往用在網(wǎng)絡(luò)上,客戶端和服務(wù)端是通過網(wǎng)絡(luò)連接的。

所有的數(shù)據(jù)都需要通過網(wǎng)絡(luò)傳輸,因此就需要有一個網(wǎng)絡(luò)傳輸層。網(wǎng)絡(luò)傳輸層需要把 Call ID 和序列化后的參數(shù)字節(jié)流傳給服務(wù)端,然后再把序列化后的調(diào)用結(jié)果傳回客戶端。

只要能完成這兩者的,都可以作為傳輸層使用。因此,它所使用的協(xié)議其實是不限的,能完成傳輸就行。

盡管大部分 RPC 框架都使用 TCP 協(xié)議,但其實 UDP 也可以,而 gRPC 干脆就用了 HTTP2。

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

所以,要實現(xiàn)一個 RPC 框架,只需要把以下三點實現(xiàn)了就基本完成了:

  • Call ID 映射:可以直接使用函數(shù)字符串,也可以使用整數(shù) ID。映射表一般就是一個哈希表。
  • 序列化反序列化:可以自己寫,也可以使用 Protobuf 或者 FlatBuffers 之類的。
  • 網(wǎng)絡(luò)傳輸庫:可以自己寫 Socket,或者用 Asio,ZeroMQ,Netty 之類。

RPC 核心之網(wǎng)絡(luò)傳輸協(xié)議

在第三節(jié)中說明了要實現(xiàn)一個 RPC,需要選擇網(wǎng)絡(luò)傳輸?shù)姆绞健?/p>

 

圖 10:網(wǎng)絡(luò)傳輸

在 RPC 中可選的網(wǎng)絡(luò)傳輸方式有多種,可以選擇 TCP 協(xié)議、UDP 協(xié)議、HTTP 協(xié)議。

每一種協(xié)議對整體的性能和效率都有不同的影響,如何選擇一個正確的網(wǎng)絡(luò)傳輸協(xié)議呢?首先要搞明白各種傳輸協(xié)議在 RPC 中的工作方式。

基于 TCP 協(xié)議的 RPC 調(diào)用

由服務(wù)的調(diào)用方與服務(wù)的提供方建立 Socket 連接,并由服務(wù)的調(diào)用方通過 Socket 將需要調(diào)用的接口名稱、方法名稱和參數(shù)序列化后傳遞給服務(wù)的提供方,服務(wù)的提供方反序列化后再利用反射調(diào)用相關(guān)的方法。

***將結(jié)果返回給服務(wù)的調(diào)用方,整個基于 TCP 協(xié)議的 RPC 調(diào)用大致如此。

但是在實例應(yīng)用中則會進(jìn)行一系列的封裝,如 RMI 便是在 TCP 協(xié)議上傳遞可序列化的 Java 對象。

基于 HTTP 協(xié)議的 RPC 調(diào)用

該方法更像是訪問網(wǎng)頁一樣,只是它的返回結(jié)果更加單一簡單。

其大致流程為:由服務(wù)的調(diào)用者向服務(wù)的提供者發(fā)送請求,這種請求的方式可能是 GET、POST、PUT、DELETE 等中的一種,服務(wù)的提供者可能會根據(jù)不同的請求方式做出不同的處理,或者某個方法只允許某種請求方式。

而調(diào)用的具體方法則是根據(jù) URL 進(jìn)行方法調(diào)用,而方法所需要的參數(shù)可能是對服務(wù)調(diào)用方傳輸過去的 XML 數(shù)據(jù)或者 JSON 數(shù)據(jù)解析后的結(jié)果,***返回 JOSN 或者 XML 的數(shù)據(jù)結(jié)果。

由于目前有很多開源的 Web 服務(wù)器,如 Tomcat,所以其實現(xiàn)起來更加容易,就像做 Web 項目一樣。

兩種方式對比

基于 TCP 的協(xié)議實現(xiàn)的 RPC 調(diào)用,由于 TCP 協(xié)議處于協(xié)議棧的下層,能夠更加靈活地對協(xié)議字段進(jìn)行定制,減少網(wǎng)絡(luò)開銷,提高性能,實現(xiàn)更大的吞吐量和并發(fā)數(shù)。

但是需要更多關(guān)注底層復(fù)雜的細(xì)節(jié),實現(xiàn)的代價更高。同時對不同平臺,如安卓,iOS 等,需要重新開發(fā)出不同的工具包來進(jìn)行請求發(fā)送和相應(yīng)解析,工作量大,難以快速響應(yīng)和滿足用戶需求。

基于 HTTP 協(xié)議實現(xiàn)的 RPC 則可以使用 JSON 和 XML 格式的請求或響應(yīng)數(shù)據(jù)。

而 JSON 和 XML 作為通用的格式標(biāo)準(zhǔn)(使用 HTTP 協(xié)議也需要序列化和反序列化,不過這不是該協(xié)議下關(guān)心的內(nèi)容,成熟的 Web 程序已經(jīng)做好了序列化內(nèi)容),開源的解析工具已經(jīng)相當(dāng)成熟,在其上進(jìn)行二次開發(fā)會非常便捷和簡單。

但是由于 HTTP 協(xié)議是上層協(xié)議,發(fā)送包含同等內(nèi)容的信息,使用 HTTP 協(xié)議傳輸所占用的字節(jié)數(shù)會比使用 TCP 協(xié)議傳輸所占用的字節(jié)數(shù)更高。

因此在同等網(wǎng)絡(luò)下,通過 HTTP 協(xié)議傳輸相同內(nèi)容,效率會比基于 TCP 協(xié)議的數(shù)據(jù)效率要低,信息傳輸所占用的時間也會更長,當(dāng)然壓縮數(shù)據(jù),能夠縮小這一差距。

使用 RabbitMQ 的 RPC 架構(gòu)

在 OpenStack 中服務(wù)與服務(wù)之間使用 RESTful API 調(diào)用,而在服務(wù)內(nèi)部則使用 RPC 調(diào)用各個功能模塊。

正是由于使用了 RPC 來解耦服務(wù)內(nèi)部功能模塊,使得 OpenStack 的服務(wù)擁有擴展性強,耦合性低等優(yōu)點。

OpenStack 的 RPC 架構(gòu)中,加入了消息隊列 RabbitMQ,這樣做的目的是為了保證 RPC 在消息傳遞過程中的安全性和穩(wěn)定性。

下面分析 OpenStack 中使用 RabbitMQ 如何實現(xiàn) RPC 的調(diào)用。

RabbitMQ 簡介

以下摘錄自知乎:

對于初學(xué)者,舉一個飯店的例子來解釋這三個分別是什么吧。不是***恰當(dāng),但是應(yīng)該足以解釋這三者的區(qū)別。

RPC:假設(shè)你是一個飯店里的服務(wù)員,顧客向你點菜,但是你不會做菜,所以你采集了顧客要點什么之后告訴后廚去做顧客點的菜,這叫 RPC(remote procedure call),因為廚房的廚師相對于服務(wù)員而言是另外一個人(在計算機的世界里就是 Remote 的機器上的一個進(jìn)程)。廚師做好了的菜就是RPC的返回值。

任務(wù)隊列和消息隊列:本質(zhì)都是隊列,所以就只舉一個任務(wù)隊列的例子。假設(shè)這個飯店在高峰期顧客很多,而廚師只有很少的幾個,所以服務(wù)員們不得不把單子按下單順序放在廚房的桌子上,供廚師們一個一個做,這一堆單子就是任務(wù)隊列,廚師們每做完一個菜,就從桌子上的訂單里再取出一個單子繼續(xù)做菜。

角色分擔(dān)如下圖:

 

圖 11:RabbitMQ 在 RPC 中角色

使用 RabbitMQ 的好處:

  • 同步變異步:可以使用線程池將同步變成異步,但是缺點是要自己實現(xiàn)線程池,并且強耦合。使用消息隊列可以輕松將同步請求變成異步請求。
  • 低內(nèi)聚高耦合:解耦,減少強依賴。
  • 流量削峰:通過消息隊列設(shè)置請求***值,超過閥值的拋棄或者轉(zhuǎn)到錯誤界面。
  • 網(wǎng)絡(luò)通信性能提高:TCP 的創(chuàng)建和銷毀開銷大,創(chuàng)建 3 次握手,銷毀 4 次分手,高峰時成千上萬條的鏈接會造成資源的巨大浪費,而且操作系統(tǒng)每秒處理 TCP 的數(shù)量也是有數(shù)量限制的,必定造成性能瓶頸。

RabbitMQ 采用信道通信,不采用 TCP 直接通信。一條線程一條信道,多條線程多條信道,公用一個 TCP 連接。

一條 TCP 連接可以容納***條信道(硬盤容量足夠的話),不會造成性能瓶頸。

RabbitMQ 的三種類型的交換器

RabbitMQ 使用 Exchange(交換機)和 Queue(隊列)來實現(xiàn)消息隊列。

在 RabbitMQ 中一共有三種交換機類型,每一種交換機類型都有很鮮明的特征。

基于這三種交換機類型,OpenStack 完成兩種 RPC 的調(diào)用方式。首先簡單介紹三種交換機。

 

圖 12:RabbitMQ 架構(gòu)圖

①廣播式交換器類型(Fanout)

該類交換器不分析所接收到消息中的 Routing Key,默認(rèn)將消息轉(zhuǎn)發(fā)到所有與該交換器綁定的隊列中去。

 

圖 13:廣播式交換機

②直接式交換器類型(Direct)

該類交換器需要精確匹配 Routing Key 與 Binding Key,如消息的 Routing Key = Cloud,那么該條消息只能被轉(zhuǎn)發(fā)至 Binding Key = Cloud 的消息隊列中去。

 

圖 14:直接式交換機

③主題式交換器(Topic Exchange)

該類交換器通過消息的 Routing Key 與 Binding Key 的模式匹配,將消息轉(zhuǎn)發(fā)至所有符合綁定規(guī)則的隊列中。

Binding Key 支持通配符,其中“*”匹配一個詞組,“#”匹配多個詞組(包括零個)。

 

圖 15:主題式交換機

注:以上四張圖片來自博客園,如有侵權(quán),請聯(lián)系作者:https://www.cnblogs.com/dwlsxj/p/RabbitMQ.html。

當(dāng)生產(chǎn)者發(fā)送消息 Routing Key=F.C.E 的時候,這時候只滿足 Queue1,所以會被路由到 Queue 中。

如果 Routing Key=A.C.E 這時候會被同時路由到 Queue1 和 Queue2 中,如果 Routing Key=A.F.B 時,這里只會發(fā)送一條消息到 Queue2 中。

Nova 基于 RabbitMQ 實現(xiàn)兩種 RPC 調(diào)用:

  • RPC.CALL(調(diào)用)
  • RPC.CAST(通知)

其中 RPC.CALL 基于請求與響應(yīng)方式,RPC.CAST 只是提供單向請求,兩種 RPC 調(diào)用方式在 Nova 中均有典型的應(yīng)用場景。

RPC.CALL

RPC.CALL 是一種雙向通信流程,即 RabbitMQ 接收消息生產(chǎn)者生成的系統(tǒng)請求消息,消息消費者經(jīng)過處理之后將系統(tǒng)相應(yīng)結(jié)果反饋給調(diào)用程序。

 

圖 16:RPC.CALL 原理圖

一個用戶通過 Dashboard 創(chuàng)建一個虛擬機,界面經(jīng)過消息封裝后發(fā)送給 NOVA-API。

NOVA-API 作為消息生產(chǎn)者,將該消息以 RPC.CALL 方式通過 Topic 交換器轉(zhuǎn)發(fā)至消息隊列。

此時,Nova-Compute 作為消息消費者,接收該信息并通過底層虛擬化軟件執(zhí)行相應(yīng)虛擬機的啟動進(jìn)程。

待用戶虛擬機成功啟動之后,Nova-Compute 作為消息生產(chǎn)者通過 Direct 交換器和響應(yīng)的消息隊列將虛擬機啟動成功響應(yīng)消息反饋給 Nova-API。

此時 Nova-API 作為消息消費者接收該消息并通知用戶虛擬機啟動成功。

 

RPC.CALL 工作原理如下圖:

 

圖 17:RPC.CALL 具體實現(xiàn)圖

工作流程:

  • 客戶端創(chuàng)建 Message 時指定 reply_to 隊列名、correlation_id 標(biāo)記調(diào)用者。
  • 通過隊列,服務(wù)端收到消息。調(diào)用函數(shù)處理,然后返回。
  • 返回的隊列是 reply_to 指定的隊列,并攜帶 correlation_id。
  • 返回消息到達(dá)客戶端,客戶端根據(jù) correlation_id 判斷是哪一個函數(shù)的調(diào)用返回。

如果有多個線程同時進(jìn)行遠(yuǎn)程方法調(diào)用,這時建立在 Client Server 之間的 Socket 連接上會有很多雙方發(fā)送的消息傳遞,前后順序也可能是隨機的。

Server 處理完結(jié)果后,將結(jié)果消息發(fā)送給 Client,Client 收到很多消息,怎么知道哪個消息結(jié)果是原先哪個線程調(diào)用的?

Client 線程每次通過 Socket 調(diào)用一次遠(yuǎn)程接口前,生成一個唯一的 ID,即 Request ID(Request ID必需保證在一個 Socket 連接里面是唯一的),一般常常使用 AtomicLong 從 0 開始累計數(shù)字生成唯一 ID。

RPC.CAST

RPC.CAST 的遠(yuǎn)程調(diào)用流程與 RPC.CALL 類似,只是缺少了系統(tǒng)消息響應(yīng)流程。

一個 Topic 消息生產(chǎn)者發(fā)送系統(tǒng)請求消息到 Topic 交換器,Topic 交換器根據(jù)消息的 Routing Key 將消息轉(zhuǎn)發(fā)至共享消息隊列。

與共享消息隊列相連的所有 Topic 消費者接收該系統(tǒng)請求消息,并把它傳遞給響應(yīng)的服務(wù)端進(jìn)行處理。

其調(diào)用流程如圖所示:

 

圖 18:RPC.CAST 原理圖

連接設(shè)計

RabbitMQ 實現(xiàn)的 RPC 對網(wǎng)絡(luò)的一般設(shè)計思路:消費者是長連接,發(fā)送者是短連接。但可以自由控制長連接和短連接。

一般消費者是長連接,隨時準(zhǔn)備接收處理消息;而且涉及到 RabbitMQ Queues、Exchange 的 auto-deleted 等沒特殊需求沒必要做短連接。發(fā)送者可以使用短連接,不會長期占住端口號,節(jié)省端口資源。

Nova 中 RPC 代碼設(shè)計:

 

簡單對比 RPC 和 Restful API

RESTful API 架構(gòu)

REST ***的幾個特點為:資源、統(tǒng)一接口、URI 和無狀態(tài)。

①資源

所謂"資源",就是網(wǎng)絡(luò)上的一個實體,或者說是網(wǎng)絡(luò)上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務(wù),就是一個具體的實在。

②統(tǒng)一接口

RESTful 架構(gòu)風(fēng)格規(guī)定,數(shù)據(jù)的元操作,即 CRUD(Create,Read,Update 和 Delete,即數(shù)據(jù)的增刪查改)操作,分別對應(yīng)于 HTTP 方法:GET 用來獲取資源,POST 用來新建資源(也可以用于更新資源),PUT 用來更新資源,DELETE 用來刪除資源,這樣就統(tǒng)一了數(shù)據(jù)操作的接口,僅通過 HTTP 方法,就可以完成對數(shù)據(jù)的所有增刪查改工作。

③URL

可以用一個 URI(統(tǒng)一資源定位符)指向資源,即每個 URI 都對應(yīng)一個特定的資源。

要獲取這個資源,訪問它的 URI 就可以,因此 URI 就成了每一個資源的地址或識別符。

④無狀態(tài)

所謂無狀態(tài)的,即所有的資源,都可以通過 URI 定位,而且這個定位與其他資源無關(guān),也不會因為其他資源的變化而改變。有狀態(tài)和無狀態(tài)的區(qū)別,舉個簡單的例子說明一下。

如查詢員工的工資,如果查詢工資是需要登錄系統(tǒng),進(jìn)入查詢工資的頁面,執(zhí)行相關(guān)操作后,獲取工資的多少,則這種情況是有狀態(tài)的。

因為查詢工資的每一步操作都依賴于前一步操作,只要前置操作不成功,后續(xù)操作就無法執(zhí)行。

如果輸入一個 URI 即可得到指定員工的工資,則這種情況是無狀態(tài)的,因為獲取工資不依賴于其他資源或狀態(tài)。

且這種情況下,員工工資是一個資源,由一個 URI 與之對應(yīng),可以通過 HTTP 中的 GET 方法得到資源,這是典型的 RESTful 風(fēng)格。

RPC 和 Restful API 對比

面對對象不同:

  • RPC 更側(cè)重于動作。
  • REST 的主體是資源。

RESTful 是面向資源的設(shè)計架構(gòu),但在系統(tǒng)中有很多對象不能抽象成資源,比如登錄,修改密碼等而 RPC 可以通過動作去操作資源。所以在操作的全面性上 RPC 大于 RESTful。

傳輸效率:

  • RPC 效率更高。RPC,使用自定義的 TCP 協(xié)議,可以讓請求報文體積更小,或者使用 HTTP2 協(xié)議,也可以很好的減少報文的體積,提高傳輸效率。

復(fù)雜度:

  • RPC 實現(xiàn)復(fù)雜,流程繁瑣。
  • REST 調(diào)用及測試都很方便。

RPC 實現(xiàn)(參見***節(jié))需要實現(xiàn)編碼,序列化,網(wǎng)絡(luò)傳輸?shù)?。?RESTful 不要關(guān)注這些,RESTful 實現(xiàn)更簡單。

靈活性:

  • HTTP 相對更規(guī)范,更標(biāo)準(zhǔn),更通用,無論哪種語言都支持 HTTP 協(xié)議。
  • RPC 可以實現(xiàn)跨語言調(diào)用,但整體靈活性不如 RESTful。

總結(jié)

RPC 主要用于公司內(nèi)部的服務(wù)調(diào)用,性能消耗低,傳輸效率高,實現(xiàn)復(fù)雜。

HTTP 主要用于對外的異構(gòu)環(huán)境,瀏覽器接口調(diào)用,App 接口調(diào)用,第三方接口調(diào)用等。

RPC 使用場景(大型的網(wǎng)站,內(nèi)部子系統(tǒng)較多、接口非常多的情況下適合使用 RPC):

  • 長鏈接。不必每次通信都要像 HTTP 一樣去 3 次握手,減少了網(wǎng)絡(luò)開銷。
  • 注冊發(fā)布機制。RPC 框架一般都有注冊中心,有豐富的監(jiān)控管理;發(fā)布、下線接口、動態(tài)擴展等,對調(diào)用方來說是無感知、統(tǒng)一化的操作。
  • 安全性,沒有暴露資源操作。
  • 微服務(wù)支持。就是最近流行的服務(wù)化架構(gòu)、服務(wù)化治理,RPC 框架是一個強力的支撐。

【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2021-02-01 09:04:42

Python 項目distutils

2021-04-12 07:36:15

Scrapy爬蟲框架

2021-06-13 12:03:46

SaaS軟件即服務(wù)

2021-10-09 00:02:04

DevOps敏捷開發(fā)

2022-03-27 20:32:28

Knative容器事件模型

2020-03-09 09:13:40

HTTPSTCP網(wǎng)絡(luò)協(xié)議

2021-09-13 08:41:52

職場互聯(lián)網(wǎng)自閉

2022-07-31 20:29:28

日志系統(tǒng)

2021-02-14 00:21:37

區(qū)塊鏈數(shù)字貨幣金融

2021-03-03 21:31:24

量化投資利潤

2021-06-29 11:21:41

數(shù)據(jù)安全網(wǎng)絡(luò)安全黑客

2020-11-30 08:34:44

大數(shù)據(jù)數(shù)據(jù)分析技術(shù)

2022-04-12 18:29:41

元數(shù)據(jù)系統(tǒng)架構(gòu)

2022-01-05 18:27:44

數(shù)據(jù)挖掘工具

2022-04-22 11:26:55

數(shù)據(jù)管理架構(gòu)

2021-10-17 20:38:30

微服務(wù)內(nèi)存組件

2020-11-03 07:04:39

云計算公有云私有云

2021-03-25 11:24:25

爬蟲技術(shù)開發(fā)

2022-04-27 18:25:02

數(shù)據(jù)采集維度

2021-10-12 18:31:40

流量運營前端
點贊
收藏

51CTO技術(shù)棧公眾號