如何自己實現一個RPC框架?


開源的RPC框架,大家都用過Dubbo,底層源碼大部分人為了面試也都看過了,服務暴露過程和服務引用過程,服務調用流程等,但那都是多多少少不那么純粹,就算是自己學習,也終究是站在巨人的肩膀上,你的思路在你看Dubbo源碼的那一刻就被Dubbo的路子限制住了,讓你覺得,RPC框架,就只能這么干,如果你自己實現,你要怎么實現?

 

首先

RPC框架和微服務框架:個人認為,RPC框架強調的是遠程過程調用這一功能的實現,但是像網關/服務降級/限流/熔斷等,只是RPC框架的衍生品,屬於生態周邊。比如Dubbo,在熔斷方面很弱,但是專業事情交給專業人,hystrix和sentinel不就是專門做限流熔斷的嗎?而SpringCloud,則是一整套解決方案,不僅僅局限於RPC框架了,人家從前到后都有單獨的模塊,網關zool,熔斷器hystrix,客戶端feign,注冊中心eureka等,SpringCloud更像一個微服務框架,強調的是微服務一整套解決方案,不僅僅RPC。

 

正題

RPC框架的基本是什么?是通訊,基於TCP傳輸的模型有什么:BIO和NIO,成熟的框架有Netty和Mina。

 

通訊只是基本手段,那么下一步要考慮的問題就是,數據傳輸怎么做?要傳輸什么樣的數據?

我們初學都學過BIO,寫過聊天室,傳輸的數據都是個String,輸入字符串,輸出字符串,簡單。

如果我們要傳輸對象呢?可以用ObjectInputStream和ObjectOutputStream + ByteArrayInputStream和ByteArrayOutputStream來實現對象的序列化和反序列化。

如果我們要求,在客戶端傳遞的任何對象比如User,到了服務端都能自動變成對象類型User,而不是Object呢?那么我們是不是可以傳遞對象的Class信息,到了服務端,利用獲取到的Class信息,把Object加工成User對象。

如果我們要求,客戶端拿着一份接口,調用里面的方法,就能拿到服務端那邊接口的實現類返回的數據,就像本地調用一樣絲滑呢?那么這就是RPC調用的需求。

1. 客戶端和服務端建立好通訊,保證道路暢通

2. 客戶端這邊調用接口的方法的時候,我們要收集好接口+方法信息+參數信息,打包好(收集數據+序列化)並發送。

3. 服務端這邊呢,接收到客戶端的數據,拆包(反序列化),拿到接口信息,找到該接口的實現類;拿到方法信息,找到實現類中對應的方法;拿到參數信息,傳入具體的參數值,調用實現類中的方法;實現類返回數據,服務端將返回數據和返回類型打包(序列化),發送給客戶端。

4. 客戶端拿到服務端返回的數據,展示給用戶。

這只是個簡單的思路,實際上里面還有很多細節,比如:

1. 並發情況下,數據傳輸會亂序。

2. 如何知道,服務端返回的數據,是給哪一個方法的?

3. 客戶端的接口是無法實例化的,接口怎樣調用?調用之后如何與客戶端搭上關系?

4. 如何確定客戶端要調用服務端的哪一個方法,確定之后,用反射調用嗎?

5. 客戶端超時了怎么辦?

數據傳輸做好之后,客戶端和服務端接口提供與消費的同步怎么做?也就是服務注冊與發現,因為現實中,不可能單客戶端和單服務端。

這部分還是很好理解的,服務注冊與發現需要一個注冊中心,注冊中心就是一個第三方。類似於買家/買家/中間商的關系,買家和賣家不直接接觸,完全靠中間商互通有無。

這里可以說一下CAP:

CAP分別是(數據)一致性,(服務器)可用性和分區容錯性(分布式系統中在部分斷網的情況下仍然可以完全正常的工作)。那么一個分布式系統中,P是必須的,剩下就在CA中選一個。

Zookeeper只能保證CP,一致性和分區容錯性:不能保證可用性(A)是因為Master選舉的過程中,整個集群是不可用的。

Eureka可以保證AP,可用性和分區容錯性:當單個服務器掛掉的情況下,我還可以請求其它服務器(可用性),只是當前服務器的數據可能不是最新的(一致性)

我覺得一個最基本,最純粹的RPC流程是這樣的:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM