漫話:如何給女朋友解釋什麼是RPC
週末一大早,我正在電腦前面看新聞,突然女朋友大喊起來:哇,杭州下大雪啦,快來看啊。我並沒有理她,於是她跑過來拉我。
雪後杭州RPC 是Remote Procedure Call的縮寫,譯為遠端過程呼叫。是一個計算機通訊協議。
為什麼需要遠端呼叫
在如何給女朋友解釋什麼是分散式這一篇文章中介紹過,為了提升飯店的服務能力,飯店從一開始只有一個負責所有事情的廚師發展成有廚師、切菜師、備菜師等多個角色。
在飯店只有一個廚師的時候,廚師想要做出一道美味的番茄炒蛋的時候,他需要自己洗番茄、切番茄、打雞蛋、炒菜。整個過程不需要其他人蔘與自己就完全可以完成了。這就是古老的集中式應用中,一臺單體計算機就可以搞定所有事情了。
製作番茄炒蛋{
廚師->洗菜->切菜->炒菜
}
複製程式碼
隨著飯店發展,需要明確分工,讓專業的人負責專業的事兒。所以,整個做菜過程中不再只有廚師參與了。需要有多個角色,備菜師傅負責準備番茄和雞蛋、切菜師傅負責切菜、廚師只要負責炒菜就行了。
但是,隨著分工明確,製作番茄炒蛋的過程不再是隻有一個人參與的過程了。這個過程中需要多方協作。廚師準備炒菜之前,需要先通知備菜師傅和切菜師傅,前序工作準備好之後才能進行炒菜。
製作番茄炒蛋{
備菜師->洗菜
切菜師->切菜
廚師->炒菜
}
複製程式碼
這種情況下,廚師就要依賴很多外人來參與這個炒菜工作。而他在通知備菜師幫他洗菜,通知切菜師傅幫他切菜的時候,這個過程就是遠端過程呼叫。
大多數情況下,一般是服務員直接到廚房下單,然後後廚有一個人員分別把選單分發給備菜師、切菜師和廚師。
這個過程就和計算機系統很像了。如今的大型網站都是分散式部署的。拿一個下單流程來說,可能涉及到物流、支付、庫存、紅包等多個系統後,而多個系統又是分別部署在不同的機器上的,分別由不同的團隊負責。而要想實現下單流程,就需要用到遠端呼叫。
下單{
庫存->減少庫存
支付->扣款
紅包->紅包抵用
物流->生成物流資訊
}
複製程式碼
到底什麼是遠端過程呼叫
RPC 是指計算機 A 上的程序,呼叫另外一臺計算機 B 上的程序,其中 A 上的呼叫程序被掛起,而 B 上的被呼叫程序開始執行,當值返回給 A 時,A 程序繼續執行。呼叫方可以通過使用引數將資訊傳送給被呼叫方,而後可以通過傳回的結果得到資訊。而這一過程,對於開發人員來說是透明的。
就像後廚的例子一樣,服務員把選單傳給後廚,廚師告訴備菜師和洗菜師開始工作,然後他等待他們完成工作。備菜師和洗菜師工作完之後,廚師開始炒菜。這個過程對於服務員來說其實是透明的,他不需要關心到底後廚是怎麼做菜的。
 由於各服務部署在不同機器上,要想在服務間進行遠端呼叫免不了網路通訊過程,服務消費方每呼叫一個服務都要寫一坨網路通訊相關的程式碼,不僅複雜而且極易出錯。如果有一種方式能讓我們像呼叫本地服務一樣呼叫遠端服務,而讓呼叫者對網路通訊這些細節透明,那麼將大大提高生產力,比如服務消費方在執行orderService.buy("HHKB鍵盤")
時,實質上呼叫的是遠端的服務。這種方式其實就是RPC。而提供了這種功能的工具我們稱之為RPC框架。
在RPC框架中主要有三個角色:Provider、Consumer和Registry。如下圖所示:
 Server: 暴露服務的服務提供方。 Client: 呼叫遠端服務的服務消費方。 Registry: 服務註冊與發現的註冊中心。服務提供方和服務消費方都比較好理解,就是後廚的洗菜師和廚師啦。廚師就是服務消費方,洗菜師就是服務提供方。廚師依賴洗菜師提供的服務。
服務註冊中心又是個什麼東西呢?
其實這個也比較好理解。對於那種很大的飯店來說,廚師可能有很多(叢集部署),洗菜師也有很多(叢集部署)。而廚師想要洗菜師幫忙洗菜的時候,他不會直接找某個洗菜師,而是通知一箇中間人,這個人可能是洗菜師團隊的領導,也可能就是一個專門協調後廚的人員。他知道整個廚房有多少洗菜師,也知道哪個洗菜師今天來上班了(需要先進行服務註冊)。而且,他還可以根據各個洗菜師的忙碌情況動態分配任務(負載均衡)。
這個中間人就是服務註冊中心。
 服務提供者啟動後主動向註冊中心註冊機器ip、port以及提供的服務列表; 服務消費者啟動時向註冊中心獲取服務提供方地址列表,可實現軟負載均衡和Failover;實現RPC需要用到的技術
一個成熟的RPC框架需要考慮的問題有很多,這裡只介紹實現一個遠端呼叫需要用到的基本技術,感興趣的朋友可以找一些開源的RPC框架程式碼來看下。
動態代理
生成 client stub和server stub需要用到Java 動態代理技術,我們可以使用JDK原生的動態代理機制,可以使用一些開源位元組碼工具框架 如:CgLib、Javassist等。
序列化
為了能在網路上傳輸和接收 Java物件,我們需要對它進行序列化和反序列化操作。
可以使用Java原生的序列化機制,但是效率非常低,推薦使用一些開源的、成熟的序列化技術,例如:protobuf、Thrift、hessian、Kryo、Msgpack
NIO
當前很多RPC框架都直接基於netty這一IO通訊框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推薦使用Netty 作為底層通訊框架。
服務註冊中心
可選技術: Redis、Zookeeper、Consul、Etcd
參考資料 :https://www.jianshu.com/p/dbfac2b876b1
開源RPC框架
Dubbo
Dubbo 是阿里巴巴公司開源的一個Java高效能優秀的服務框架,使得應用可通過高效能的 RPC 實現服務的輸出和輸入功能,可以和 Spring框架無縫整合。目前已經進入Apache孵化器。
Motan
Motan是新浪微博開源的一個Java RPC框架。2016年5月開源。Motan 在微博平臺中已經廣泛應用,每天為數百個服務完成近千億次的呼叫。
gRPC
gRPC是Google開發的高效能、通用的開源RPC框架,其由Google主要面向移動應用開發並基於HTTP/2協議標準而設計,基於ProtoBuf(Protocol Buffers)序列化協議開發,且支援眾多開發語言。本身它不是分散式的,所以要實現上面的框架的功能需要進一步的開發。
thrift
thrift是Apache的一個跨語言的高效能的服務框架,也得到了廣泛的應用。