本文引用了后端技術指南針公眾號“淺談RPC那些事兒1”和即時通訊網的“即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途”兩篇文章的部分內容。
1、引言
經常有開發者在糾結怎么開發IM集群,雖然真正的使用人數,可能用個人電腦單機都能支撐。
你也許會說,明明不需要用到IM集群,干嗎要自找麻煩?答曰:“老板說這個得有!”、“萬一產品做成了,用戶量達到百萬、千萬級呢?”,各種回答,反此種種。總之,IM集群就是得整一個(先甭管用不用的上...)。
當然,玩笑歸玩笑,真正要做到可投入到生產級別的IM集群系統,難度還是相當大的。必竟IM這種長連接應用相比傳統Http這種短連接應用太不標準。
我們以一個典型的IM聊天消息傳輸為例:
假設存在兩個正在聊天的用戶(用戶A和用戶B),當A連接的是IM集群中的IM實例1、B連接的是IM集群中的IM實例2,此時當用戶A向用戶B發送一條聊天消息時,這條消息應該如何傳遞呢?
我們梳理一下上面這個例子的消息流轉過程:
- 1)IM聊天消息首先會由用戶A發往IM實例1;
- 2)IM實例1會將此條消息轉交給IM實例2;
- 3)IM實例2會將此條消息最終投遞給連接在本實例上的用戶B。
如上述流程所示,這就是一個IM集群系統中典型的聊天消息投遞過程。
那么,這其中涉及到一個關鍵步驟:即第2)步中如何實現“IM實例1會將此條消息轉交給IM實例2”?
此時,RPC技術出場了!

▲ 上圖是個典型的分布式IM架構,注意中間的“RPC通信”字樣(本圖引用自《基于Go的馬蜂窩旅游網分布式IM系統技術實踐》)
本文將以通俗易懂的白話形式,幫你快速理解IM集群中的關鍵技術——RPC。
推薦閱讀:另一篇RPC基礎知識文章也值得一讀《即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途》。
本文已同步發布于“即時通訊技術圈”公眾號,歡迎關注:

▲ 本文在公眾號上的鏈接是:https://mp.weixin.qq.com/s/0RXTUWHXDmMddsPVWej2Qg
2、相關文章
▼ 以下兩篇文章有助于您對RPC和IM集群有個初步的概念:
▼ IM開發干貨系列文章(本文是其第24篇):
《IM消息送達保證機制實現(一):保證在線實時消息的可靠投遞》
《一種Android端IM智能心跳算法的設計與實現探討(含樣例代碼)》
《IM開發基礎知識補課(一):正確理解前置HTTP SSO單點登陸接口的原理》
《IM開發基礎知識補課(二):如何設計大量圖片文件的服務端存儲架構?》
《IM開發基礎知識補課(三):快速理解服務端數據庫讀寫分離原理及實踐建議》
《IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token》
《IM群聊消息究竟是存1份(即擴散讀)還是存多份(即擴散寫)?》
《IM開發基礎知識補課(五):通俗易懂,正確理解并用好MQ消息隊列》
《IM開發基礎知識補課(六):數據庫用NoSQL還是SQL?讀這篇就夠了!》
《IM里“附近的人”功能實現原理是什么?如何高效率地實現它?》
《IM開發基礎知識補課(七):主流移動端賬號登錄方式的原理及設計思路》
《IM開發基礎知識補課(八):史上最通俗,徹底搞懂字符亂碼問題的本質》
如果您是IM開發初學者,強烈建議首先閱讀《新手入門一篇就夠:從零開發移動端IM》。
3、正文概述
限于篇幅原因,本文不會深入展開RPC的底層技術原理,會盡量用通俗白話的方式對概念性的東西進行講解。
通過本文你將主要了解到以下內容:
- 1)什么是RPC;
- 2)為什么需要RPC;
- 3)RPC的重要組件;
- 4)常見RPC框架和各自特點。
4、什么是RPC?
RPC 是1984年代由 Andrew D. Birrell & Bruce Jay Nelson 提出的(見二位大佬的論文《Implementing Remote Procedure Calls》),所以它并不是最近才有的技術概念。
關于RPC的介紹,正經的資料上大概是這樣介紹的:
RPC(Remote Procedure Call)遠程過程調用,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。也就是說兩臺服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的方法,由于不在一個內存空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的數據。
大白話理解RPC就是:RPC讓你用別人家的東西就像自己家的一樣。
看得我似懂非懂,于是我不得不問幾個問題:
- 1)為啥要用別人家的東西——請求其他服務);
- 2)我怎么可以借到別人家的東西——其他服務調用;
- 3)要是借用的話哪種形式更好——確定一個合適的調用方法);
- 4)怎么讓我用別人東西像自己的一樣——屏蔽底層細節透明通信)。
在解答這些問題之前,我們必須達到一個共識問題:RPC只是一種通信模式,和http并不沖突對立,相反http可以作為RPC傳輸數據的一種協議,把RPC當作一種模式和思想,我們才能更好地理解它。
更嚴謹的RPC基礎知識介紹,請閱讀:《即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途》。
5、為什么需要RPC?
以大家最熟悉的電商系統為例,這樣規模的分布式系統,需要拆分出用戶服務、商品服務、優惠券服務、支付服務、訂單服務、物流服務、售后服務等等。這些服務之間都相互調用,這時內部調用最好使用 RPC ,同時每個服務都可以獨立部署,獨立上線。
也就說當我們的項目太大,需要解耦服務,擴展性強、部署靈活,這時就要用到 RPC ,這主要是解決了分布式系統中,服務與服務之間的調用問題。

▲ 上圖中的分布系統內部,就是用RPC實現的(本圖引用自《從新手到架構師,一篇就夠:從100到1000萬高并發的架構演進之路》)
對于IM集群這樣的分布式系統來說,不同IM實例間的用戶聊天消息,就是通過RPC進行流轉的。
6、為什么不直接使用HTTP,而要搞RPC?
在日常業務中我們可以把功能封裝成靜態庫、動態庫、sdk、獨立服務等,最常見也最方便的還是HTTP這種形式的調用。
HTTP服務把需要提供的服務暴露成接口(也就是通常所說的http rest接口啦),使用方直接按約定的HTTP方法和URI進行數據交互。
我們都知道HTTP協議是應用層協議,是個非常標準的協議,在HTTP協議之下還有網絡層、傳輸層、數據鏈路層等,一個數據包packet除了凈荷payload之外還有很多header,由于標準和通用性的設計目標也使得HTTP一次數據交互真正傳輸的payload只是其中一部分。

HTTP是我們用的最多最熟悉的交互模式,在系統內部各個服務之間接口較少,交互不多的情況下工作得還不錯。
但如果在內部系統調用很復雜的前提下,HTTP調用的效率和安全性就不那么理想了。

以IM系統為例,單個IM實例的吞吐效率至少可以達到幾萬甚至數十萬QPS,使用HTTP這種短連接(調用時建立socket連接,完成后釋放連接)方式顯的相當低效(每次調用都要重新經歷TCP的3次握手、4次揮手過程),在分布式的情況下勢必拉低整個IM集群的吞吐效率。而對于RPC,這種socket長連接方式對于高性能場景來說,效果是顯而易見的。
更重要的是面對眾多的服務我們需要的不僅僅是一個通信方式,而是一個內部服務的管理系統,這也就是我們今天說的RPC框架。注意:RPC是一種模式策略和框架,并不是單純的通信協議。
題外話:實際上,HTTP在RPC系統中,并不是個你死我活的關系,必竟HTTP只是個通信協議,而HTTP有某些性能要求不敏感的場景來說,是完全可以作為RPC的具體實現協議之一來使用的。
7、RPC的調用過程是什么樣的?

▲ 典型的RPC調用過程
如上圖所示,一個典型的RPC調用過程是這樣(過程序號對應上圖中的數字):
- 1)客戶端(client)以本地調用方式調用服務;
- 2)客戶端存根(client stub)接收到調用后,負責將方法、參數等組裝成能夠進行網絡傳輸的消息體(將消息體對象序列化為二進制);
- 3)客戶端通過 sockets 將消息發送到服務端;
- 4)服務端存根(server stub)收到消息后進行解碼(將消息對象反序列化);
- 5)服務端存根(server stub)根據解碼結果調用本地的服務;
- 6)本地服務執行并將結果返回給服務端存根(server stub);
- 7)服務端存根(server stub)將返回結果打包成消息(將結果消息對象序列化);
- 8)服務端(server)通過 sockets 將消息發送到客戶端;
- 9)客戶端存根(client stub)接收到結果消息,并進行解碼(將結果消息發序列化);
- 10)客戶端(client)得到最終結果。
RPC的作用,其實就是要把上述2、3、4、7、8、9 這些步驟都封裝起來。是不是很神奇?
8、關于HTTP和RPC的一些爭議
HTTP和RPC是兩個很容易混淆的概念,對于剛開始接觸RPC的人來說,通常都會困惑:有HTTP了為什么還要用RPC?
在知乎上看到了這個很有趣的問題:《既然有http請求,為什么還要用rpc?》
其中一個大佬的回答感覺很有意思:

換個角度來說:HTTP 與 RPC 的關系就好比普通話與方言的關系。要進行跨企業服務調用時,往往都是通過 HTTP API,也就是普通話,雖然效率不高,但是通用,沒有太多溝通的學習成本。但是在企業內部還是 RPC 更加高效,同一個企業公用一套方言進行高效率的交流,要比通用的 HTTP 協議來交流更加節省資源。整個中國有非常多的方言,正如有很多的企業內部服務各有自己的一套交互協議一樣。雖然國家一直在提倡使用普通話交流,但是這么多年過去了,你回一趟家鄉探個親什么的就會發現身邊的人還是流行說方言。
如果再深入一點說,普通話本質上也是一種方言,只不過它是官方的方言,使用最為廣泛的方言,相比而言其它方言都是小語種,小語種之中也會有幾個使用比較廣泛比較特色的方言占比也會比較大。這就好比開源 RPC 協議中 Protobuf 和 Thrift 一樣,它們兩應該是 RPC 協議中使用最為廣泛的兩個。
總之:RPC是一種編程模式和概念,并不是非常具體的一種技術,實際上和HTTP沒有明確的沖突,HTTP可以作為RPC傳輸協議,原因還是RPCpid際上是一種內部服務框架而不是一個具體的通信協議,它可以涉及服務注冊、服務治理、服務發現、熔斷機制、負載均衡等。
9、典型的RPC框架
一個典型RPC框架中,包含了服務發現、負載、容錯、網絡傳輸、序列化等組件,其中“RPC 協議”就指明了程序如何進行網絡傳輸和序列化。

▲ 一個典型的 RPC 架構原理圖(本圖引用自《即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途》)

▲ 著名RPC框架Dubbo的架構圖(本圖引用自《即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途》)
一個 RPC 最重要的功能模塊,就是上圖中的”RPC 協議”部分:

其中的序列化和反序列化的意思是:
- 1)序列化:將數據結構或對象轉換成二進制串的過程;
- 2)反序列化:將序列化中所生成的二進制串轉換成數據結構或者對象的過程。
在網絡消息傳輸中可以基于TCP、UDP、http來實現,各自都有各自的特點。
基于 TCP 實現的 RPC 調用,能夠靈活對協議字段進行定制,減少網絡開銷提高性能,實現更大的吞吐量和并發數,但要關注底層細節,在進行數據解析時更加復雜一些(比如最受歡迎的Protobuf的使用)。
基于 HTTP 實現的 RPC 可以使用 JSON 和 XML 格式的請求或響應數據,解析工具很成熟,在其上進行二次開發會非常便捷和簡單。但是 HTTP 是上層協議,所占用的字節數會比使用 TCP 協議傳輸所占用的字節數更高。
對于其他部分,本文不再展開。
10、市面上常見的RPC框架及其特點
常見 RPC 技術和框架有:
- 1)應用級的服務框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。
- 2)遠程通信協議:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
- 3)通信框架:MINA 和 Netty。
目前流行的開源 RPC 框架還是比較多的,有阿里巴巴的 Dubbo、Facebook 的 Thrift、Google 的 gRPC、Twitter 的 Finagle 等。
下面重點介紹當前最流行的三種RPC框架主要特點:
- 1)gRPC:是 Google 公布的開源軟件,基于最新的 HTTP 2.0 協議,并支持常見的眾多編程語言。RPC 框架是基于 HTTP 協議實現的,底層使用到了 Netty 框架的支持;
- 2)Thrift:是 Facebook 的開源 RPC 框架,主要是一個跨語言的服務開發框架。用戶只要在其之上進行二次開發就行,應用對于底層的 RPC 通訊等都是透明的。不過這個對于用戶來說需要學習特定領域語言這個特性,還是有一定成本的;
- 3)Dubbo:是阿里集團開源的一個極為出名的 RPC 框架,在很多互聯網公司和企業應用中廣泛使用。協議和序列化框架都可以插拔是極其鮮明的特色。
11、本文小結
小結一下,簡單地理解RPC就是:
RPC 就是從一臺機器(客戶端)上通過參數傳遞的方式調用另一臺機器(服務器)上的一個函數或方法(可以統稱為服務)并得到返回的結果。
RPC 會隱藏底層的通訊細節(不需要直接處理Socket通訊或Http通訊)。
RPC 是一個請求響應模型。客戶端發起請求,服務器返回響應(類似于Http的工作方式)。
RPC 在使用形式上像調用本地函數(或方法)一樣去調用遠程的函數(或方法)。
12、參考資料
[1] 什么是 RPC 框架
[3] 淺談RPC那些事兒[1]
[4] 即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途
[5] 即時通訊新手入門:一文讀懂什么是Nginx?它能否實現IM的負載均衡?
附錄:有關IM架構設計的文章
《一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)》
《IM開發基礎知識補課(二):如何設計大量圖片文件的服務端存儲架構?》
《IM開發基礎知識補課(三):快速理解服務端數據庫讀寫分離原理及實踐建議》
《IM開發基礎知識補課(四):正確理解HTTP短連接中的Cookie、Session和Token》
《WhatsApp技術實踐分享:32人工程團隊創造的技術神話》
《王者榮耀2億用戶量的背后:產品定位、技術架構、網絡方案等》
《IM系統的MQ消息中間件選型:Kafka還是RabbitMQ?》
《騰訊資深架構師干貨總結:一文讀懂大型分布式系統設計的方方面面》
《子彈短信光鮮的背后:網易云信首席架構師分享億級IM平臺的技術實踐》
《知乎技術分享:從單機到2000萬QPS并發的Redis高性能緩存實踐之路》
《IM開發基礎知識補課(五):通俗易懂,正確理解并用好MQ消息隊列》
《微信技術分享:微信的海量IM聊天消息序列號生成實踐(算法原理篇)》
《微信技術分享:微信的海量IM聊天消息序列號生成實踐(容災方案篇)》
《新手入門:零基礎理解大型分布式架構的演進歷史、技術原理、最佳實踐》
《一套高可用、易伸縮、高并發的IM群聊、單聊架構方案設計實踐》
《阿里技術分享:阿里自研金融級數據庫OceanBase的艱辛成長之路》
《社交軟件紅包技術解密(一):全面解密QQ紅包技術方案——架構、技術實現等》
《社交軟件紅包技術解密(二):解密微信搖一搖紅包從0到1的技術演進》
《社交軟件紅包技術解密(三):微信搖一搖紅包雨背后的技術細節》
《社交軟件紅包技術解密(四):微信紅包系統是如何應對高并發的》
《社交軟件紅包技術解密(五):微信紅包系統是如何實現高可用性的》
《社交軟件紅包技術解密(六):微信紅包系統的存儲層架構演進實踐》
《社交軟件紅包技術解密(七):支付寶紅包的海量高并發技術實踐》
《社交軟件紅包技術解密(九):談談手Q紅包的功能邏輯、容災、運維、架構等》
《社交軟件紅包技術解密(十):手Q客戶端針對2020年春節紅包的技術實踐》
《即時通訊新手入門:一文讀懂什么是Nginx?它能否實現IM的負載均衡?》
《即時通訊新手入門:快速理解RPC技術——基本概念、原理和用途》
《多維度對比5款主流分布式MQ消息隊列,媽媽再也不擔心我的技術選型了》
《從游擊隊到正規軍(一):馬蜂窩旅游網的IM系統架構演進之路》
《從游擊隊到正規軍(二):馬蜂窩旅游網的IM客戶端架構演進和實踐總結》
《IM開發基礎知識補課(六):數據庫用NoSQL還是SQL?讀這篇就夠了!》
《瓜子IM智能客服系統的數據架構設計(整理自現場演講,有配套PPT)》
《阿里釘釘技術分享:企業級IM王者——釘釘在后端架構上的過人之處》
《從游擊隊到正規軍(三):基于Go的馬蜂窩旅游網分布式IM系統技術實踐》
《IM開發基礎知識補課(九):想開發IM集群?先搞懂什么是RPC!》
>> 更多同類文章 ……
本文已同步發布于“即時通訊技術圈”公眾號,歡迎關注:

(本文同步發布于:http://www.52im.net/thread-2996-1-1.html)
作者:Jack Jiang (點擊作者姓名進入Github)
出處:http://www.52im.net/space-uid-1.html
交流:歡迎加入即時通訊開發交流群 215891622
討論:http://www.52im.net/
Jack Jiang同時是【原創Java
Swing外觀工程BeautyEye】和【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
本博文
歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。