「RPC」簡述RPC

轉載請註明出處:https://blog.csdn.net/jinixin/article/details/80711790

 

最近工作中一直有用到Thrift,所以想對此做個簡單小結。分爲兩篇,第一篇(即本篇)介紹rpc是什麼、其與http服務的區別、基本架構、使用步驟等,第二篇介紹常用rpc框架Thrift的Python案例。

 

可能寫的有些平淡無奇或存在大量不準確之處,大家海涵。

 

 

引入

 

 

 

 

平時寫程序中我們常常會用到函數調用,而一般的函數調用都在同一個進程內。但如果現在要求某個函數去調用另個工程裏的一個函數,該怎麼辦呢?

我最先想到的是http服務,編寫RESTful風格的url並通過http請求傳遞參數從而獲得遠程工程的響應,這個方法可以很方便的在兩個程序間保持通訊。

如A工程下的a方法調用B工程下的b方法:

但有沒有辦法可以向本地調用那麼暢快呢?不用在B工程下搭建http服務器,進行構建url、序列化/反序列化數據等一系列操作,就直接了當的像下面這樣:

function a() {
    ...
    B.b()
    ...
}

答案是肯定的,這種調用方式被稱爲rpc,rpc全稱是Remote Procedure Call,即遠程過程調用,個人覺得稱爲遠程函數調用可能更貼切。

1)rpc是一種計算機通信協議,其允許程序通過網絡調用某遠程計算機上的某個服務(函數),而開發人員無需額外爲此編程。

2)使用rpc使得我們可以非常便捷的搭建分佈式系統。是不是一下子就感覺自己高大上了不少,以前聽別人談到分佈式就感覺很高深,沒想到自己現在也在搭建分佈式系統了。

3)雖然rpc是一種通信協議,但我覺得其是抽象的,不像HTTP協議那麼具體,有詳細的標準。各個公司都有自己的rpc協議,很多都做成了開源軟件。

 

 

rpc與http的區別

 

可是rpc服務相較於http服務在網間通訊上有什麼優勢呢?

1. http服務使用HTTP協議傳輸數據,其的header會在消息中佔很大比例,由於接收方不是瀏覽器,因此這部分就是廢信息,完全是在浪費帶寬。而rpc服務普遍基於TCP協議,自定義了消息格式,攜帶很少的無用信息,具有很高效率。但2015年推出的HTTP2.0協議會對header做壓縮,故使用HTTP2.0來傳輸數據也可以接受。

 

2. rpc服務普遍基於TCP協議,http服務則基於HTTP協議。我們知道在計算機網絡的工業實現中一般採用4層模型,從上至下依次爲:應用層,傳輸層,網絡層,鏈路層。

TCP協議位於傳輸層,而HTTP協議則基於TCP協議,位於應用層中。因此相較於rpc服務直接使用TCP協議包裝,http服務則需依次經過HTTP與TCP的兩次包裝,速度不言而喻。

 

3. rpc服務使用長鏈接,相較於http服務的短鏈接,避免大量三次握手所帶來的性能下降。

這條理由目前已沒那麼重要了,在HTTP1.0中需要keep-alive來建立長連接,HTTP1.1默認長連接,HTTP2.0支持多路複用,即一個連接處理多個請求,這一系列舉動在於儘量避免http服務建立連接時的過多握手。目前覺得這點可能不會太影響效率,並且Google的rpc框架GRPC就是基於HTTP2.0的。

 

從上面三點可以看出,相較於http服務,rpc服務具有更快的速度,並所需更小的帶寬。

 

4. rpc服務內部直接指明服務器ip,且傳輸的數據是經過自己編碼過的,因此具有更高的安全性。可以認爲採用http傳遞信息是在講普通話,而rpc則是講團隊黑話,具有更高的保密性

 

5. rpc服務有許多現成的rpc框架,我們自己只需去實現服務器端的一些處理函數。有關讀寫網絡內容,使用傳輸協議序列化/反序列化數據,處理器調用等操作框架會自動處理,我們不必操心。並且rpc框架還封裝了錯誤重試等特性,針對服務的穩定性和可靠性都做了優化,而單純的http服務是沒有這些特性的

 

到底選擇http服務或rpc服務來傳遞數據,還是要看具體工程,沒有絕對好壞之分,但rpc確實適合大型項目不同工程間的內部調用。另外說一下,在http服務器上增加一層封裝,也就變成了rpc服務,比如Google的GRPC框架。

 

 

rpc的架構

 

rpc是典型的客戶端/服務器模式,請求發起者是客戶端,而服務提供者是服務器。客戶端與服務器之間需要事先約定好傳輸方式與編碼協議。

個人感覺一個rpc框架逃不開四大核心組件:Client、Server、Client Stub、Server Skeleton。

1)Client:客戶端,服務的調用方

2)Server:服務端,服務的真正提供者

3)Client Stub:客戶端存根,存放有服務器地址,其將客戶端的請求打包後通過網絡發給服務方

4)Server Skeleton:服務端存根,用於接收客戶端發來的消息,將消息解包後調用服務端本地方法,並將本地方法的返回值打包後回覆給客戶端

其中的存根可以理解成是接口,即需要自己編寫代碼去實現。其目的是屏蔽客戶端調用遠程主機上某個對象的過程,其提供某種方式在本地模擬遠程對象,負責接收本地方法的調用,並將請求委派給遠端的具體執行對象。

上面的這段描述可能有些繞,下面稍作解釋(A工程下的a方法調用B工程下的b方法):

使用rpc時,A工程爲客戶端,B工程爲服務端。爲了使B工程下的b方法在a方法中可被調用,我們會在A工程裏爲b方法搞個替身c。

c方法一旦被調用,其會調用客戶端的stub,stub通過網絡調用服務端的skeleton,而skeleton則調用並返回本地b方法的執行結果。由此,a方法在調用客戶端c方法的時候,感覺上就是直接調用了遠端服務器的b方法。

 

 

 

 

 

 

使用rpc的步驟

 

雖然可供選擇的rpc框架非常多,但使用的大體流程似乎都差不多:

1. 使用類似的IDL(接口描述語言)定義數據結構和接口

2. 選擇目標語言,用框架的代碼生成引擎生成rpc的客戶端,服務端,客戶端存根,服務端存根等代碼

 

 

3. 配置客戶端與服務器,將響應客戶端請求的處理器與目標服務相綁定,也就是這個綁定過程需要開發者編寫一些代碼

 

通過上面三步整個rpc服務便搭建好了,我們可以很輕鬆的在A工程的a方法內調用B工程的b方法。

 

 

想必通過上面這些,我們已經對rpc有了大致瞭解。在第二篇中將簡單介紹Facebook的rpc框架Thrift,並給出Python實現的具體案例。文中有不當之處,望大家海涵與指出,謝謝。

 

參考鏈接:

https://blog.csdn.net/wangyunpeng0319/article/details/78651998

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章