天天看點

淺談RPC那些事兒[1]

1 前言

今天來和大家一起學習一下RPC,還是要先聲明篇幅所限,本文不會深入展開,是以本文是淺談。

還是老規矩,秉承 "最基礎的也是最重要的,最重要的也是最簡單的",不搞那麼花哨。

能讓對這個事情一無所知但是有相關經驗的人員迅速切入重點,掌握輪廓是一種重要的能力,知道别人會困在哪裡,哪些是必要的更是一種思維方式。

一個好的廚師應該也是一個美食家,如果你還是個業務仔,但是想成為架構師,不要着急,懂業務才更懂架構,架構是為業務服務的,紙上談兵的架構師也造不出好輪子。

個人認為:抽象問題和拆解問題是做好架構和業務的重要能力,在日常工作中要注意兩方面的培養。

通過本文你将了解到以下内容:

  • 什麼是RPC和為什麼需要它
  • RPC的重要元件
  • 常見RPC架構和各自特點

廢話不說,開車開車!

淺談RPC那些事兒[1]

圖來自網絡: 好奇号火星車

2 什麼是RPC以及為什麼需要它

RPC 是1984年代由 Andrew D. Birrell & Bruce Jay Nelson 提出的,是以并不是最近的概念,在二位大神的論文 "Implementing Remote Procedure Calls" :

Implementing Remote Procedure Calls http://pages.cs.wisc.edu/~sschang/OS-Qual/distOS/RPC.htm

設計目标:

Make distributed computing easy: let the programmer focus on fundamental difficulty of distributed computing: timing, independent failure of components.

Make RPC communication highly efficient: don't distort program by making programmer avoid communication due to its slowness

Make the semantics of RPC as powerful as possible without loss of simplicity or efficiency

Provide secure communication

簡單概括就是讓分布式系統更加簡單,讓開發人員把精力放到業務上,并且提供高效安全的通信。

再來看看比較常見的解釋,了解下RPC是啥:

RPC(Remote Procedure Call)遠端過程調用,它是一種通過網絡從遠端計算機程式上請求服務,而不需要了解底層網絡技術的協定。也就是說兩台伺服器A,B,一個應用部署在A伺服器上,想要調用B伺服器上應用提供的方法,由于不在一個記憶體空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的資料。

大白話了解這段話就是說:RPC讓你用别人家的東西就像自己家的一樣。

聽得我似懂非懂,于是我不得不問幾個問題:

  • 為啥要用别人家的東西(請求其他服務)
  • 我怎麼可以借到别人家的東西(其他服務調用)
  • 要是借用的話哪種形式更好(确定一個合适的調用方法)
  • 怎麼讓我用别人東西像自己的一樣(屏蔽底層細節透明通信)

闡述RPC之前我們必須達到一個共識問題:RPC隻是一種通信模式,和http并不沖突對立,相反http可以作為RPC傳輸資料的一種協定,把RPC當作一種模式和思想,我們才能更好地了解它。

2.1 為什麼要請求其他服務

典型的B/S模型或者C/S模型都是用戶端要調用服務端接口來擷取資料和結果,這種屬于外部調用。

差別于外部調用,内部系統随着業務規模的擴大,出現了分布式和微服務,簡單說就是把一個龐大的業務拆分成很多子服務,并且每個子服務都部署在很多獨立分布的機器上,進而形成一個龐大的内部系統。

生活也是如此,自給自足的農耕經濟早已經過去,不同的社會分工有不同的公司團體機構,我們要想完成自己的日常就難免和其他機關實體進行互動。

還是舉一個例子:比如我們用QQ音樂聽歌,感興趣的歌曲會做成歌單,當手機端使用者先用手機号/郵箱/第三方賬号等進行登陸,登入之後進入的自己首頁,拉取自己喜歡的歌曲歌單,最後點選播放,這個過程就涉及到多個服務的互相調用,如圖:

淺談RPC那些事兒[1]

龐大的單體程式好像逐漸沒有市場了,取而代之的是拆分之後的諸多獨立功能的服務,它們之間必然存在互相調用來實作一個綜合的功能。

2.2 如何調用其他服務

在日常業務中我們可以把功能封裝成靜态庫、動态庫、sdk、獨立服務等,最常見也最友善的還是http這種形式的調用。

http服務把需要提供的服務暴露成接口,使用方直接按約定的http方法和uri進行資料互動。

我們都知道http協定是應用層協定,是個非常标準的協定,在http協定之下還有網絡層、傳輸層、資料鍊路層等,一個資料包packet除了淨荷payload之外還有很多header,由于标準和通用性的設計目标也使得http一次資料互動真正傳輸的payload隻是其中一部分。

淺談RPC那些事兒[1]

圖來自網絡:http資料包格式

​http是我們用的最多最熟悉的互動模式,在系統内部各個服務之間接口較少,互動不多的情況下工作得還不錯。

在内部系統調用很複雜的前提下,http調用的效率和安全性就不那麼理想了,更重要的是面對衆多的服務我們需要的不僅僅是一個通信方式,而是一個内部服務的管理系統,這也就是我們今天說的RPC架構,注意RPC是一種模式政策和架構,并不是單純的通信協定。

2.3 實作遠端調用的一些思路

前面說了RPC遠端過程調用就是讓服務A像調用本地功能一樣調用遠端的服務B上的功能,不要把這個事情想的太懸乎,想想我們本地調用時需要哪些東西:确定的類或函數、類或函數的參數、類或函數的傳回值。

淺談RPC那些事兒[1]

遠端調用肯定也不會缺少這三要素,唯一的差別在于這三要素是要被傳輸過去的,這其中就涉及協定編碼和解碼的過程。

機器10.1.1.1上部署了服務A,機器10.1.1.2上部署了服務B,并且服務B上有一個add函數,int add(int a,int b),參數是兩個int 傳回值是int。

這樣服務A需要通過網絡傳輸來告訴服務B,它想要add函數,傳入的兩個參數分别是3和5,傳回的結果放在result裡面就可以。

淺談RPC那些事兒[1]

​傳輸的封包裡面按照約定的協定格式給出了函數名和參數,大緻這樣:

淺談RPC那些事兒[1]

上述的編碼隻是一種舉例不代表實際應用,旨在說明本地調用和遠端調用的唯一差別就是傳輸基本要素的方式不同,不要想的太複雜。

為了提高傳輸效率可以進行二進制編碼,比如protobuf這種。當然還有其他問題,就不再詳細展開了,這些都是我們在設計一個RPC架構時需要考慮的點。

2.4 關于http和RPC的一些辯論

http和rpc是兩個很容易混淆的概念,最開始接觸rpc的時候,我就在想有http了為什麼還要用rpc?  在知乎上看到了這個很有趣的問題:

在知乎上有個很好的問題:既然有http請求,為什麼還要用rpc? 詳情戳:https://www.zhihu.com/question/41609070

其中一個大佬的回答感覺很有意思:

淺談RPC那些事兒[1]

這個問題的諸多回答其實都表達了一個重要觀點:RPC是一種程式設計模式和概念,并不是非常具體的一種技術,并且和http沒有明确的沖突,http可以作為RPC傳輸協定,更重要的是RPC是一種内部服務架構,可以涉及服務注冊、服務治理、服務發現、熔斷機制、負載均衡等。

3.典型的RPC架構元件

前面提到了rpc不是簡單的一種協定或者技術,而是一種模式和架構,其典型的組成,如圖:

淺談RPC那些事兒[1]

圖來自網絡:rpc典型組成

RPC協定子產品是很重要的部分,這部分也是前面提到的服務A調用服務B時傳輸封包的過程,如圖:

淺談RPC那些事兒[1]

圖來自網絡:rpc協定組成

其中的序列化和反序列化定義:

序列化:将資料結構或對象轉換成二進制串的過程。

反序列化:将序列化中所生成的二進制串轉換成資料結構或者對象的過程。

在網絡消息傳輸中可以基于TCP、UDP、http來實作,各自都有各自的特點:

基于 TCP 實作的 RPC 調用,能夠靈活對協定字段進行定制,減少網絡開銷提高性能,實作更大的吞吐量和并發數,但要關注底層細節,在進行資料解析時更加複雜一些。

基于 HTTP 實作的 RPC 可以使用 JSON 和 XML 格式的請求或響應資料,解析工具很成熟,在其上進行二次開發會非常便捷和簡單。但是 HTTP 是上層協定,所占用的位元組數會比使用 TCP 協定傳輸所占用的位元組數更高。

對于其他部分,本文不再展開。

4.常見的RPC架構和各自特點

Dubbo 是阿裡巴巴公司開源的一個Java高性能優秀的服務架構,使得應用可通過高性能的 RPC 實作服務的輸出和輸入功能,可以和 Spring架構無縫內建。

Motan是新浪微網誌開源的一個Java 架構。它誕生的比較晚,起于2013年,2016年5月開源。Motan 在微網誌平台中已經廣泛應用,每天為數百個服務完成近千億次的調用。

rpcx是Go語言生态圈的Dubbo, 比Dubbo更輕量實作了Dubbo的許多特性,借助于Go語言優秀的并發特性和簡潔文法,可以使用較少的代碼實作分布式的RPC服務。

gRPC是Google開發的高性能、通用的開源RPC架構,其由Google主要面向移動應用開發并基于HTTP/2協定标準而設計,基于ProtoBuf(Protocol Buffers)序列化協定開發,且支援衆多開發語言。本身它不是分布式的,是以要實作上面的架構的功能需要進一步的開發。

thrift是Apache的一個跨語言的高性能的服務架構,也得到了廣泛的應用,Thrift是Facebook于2007年開發的,它提供多語言的編譯功能,通過Thrift的IDL來描述接口函數及資料類型,通過Thrift的編譯環境生成各種語言類型的接口檔案。

brpc(baidu-rpc)是百度開發一款遠過程調用網絡架構。目前該項目已在github上開源,brpc目前被應用于百度公司内部各種核心業務上,其中包括高性能計算和模型訓練和各種索引和排序服務,且有超過100萬以上個執行個體是基于brpc工作的。

Tars 是騰訊根據内部多年使用微服務架構的實踐,總結而成的開源項目,僅支援 C++ 語言,目前在騰訊内部應用也非常廣泛。

其中關于brpc在知乎有個很好的問題,其中有包括大神戈君(brpc主導者)在内的多個回答,可以幫助我們快速了解brpc架構:

如何評價百度開源的 RPC 架構 brpc?https://www.zhihu.com/question/65370268

5 巨人的肩膀

  • ​​https://www.w3cschool.cn/architectroad/architectroad-rpc-framework.html​​
  • ​​https://developer.51cto.com/art/201906/597963.htm​​
  • ​​https://dubbo.apache.org/zh-cn/blog/rpc-introduction.html​​
  • ​​https://colobu.com/2016/09/05/benchmarks-of-popular-rpc-frameworks/​​
  • ​​https://cloud.tencent.com/developer/article/1383845​​

繼續閱讀