亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

手寫一個RPC框架的方法教程

發布時間:2021-10-25 16:11:51 來源:億速云 閱讀:145 作者:iii 欄目:開發技術

本篇內容介紹了“手寫一個RPC框架的方法教程”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成! 

介紹

當開發一個單體項目的時候,大家肯定都寫過類似的代碼。即服務提供方和服務調用方在一個服務中

public interface HelloService {     public String sayHello(String content); }
public class HelloServiceImpl implements HelloService {      @Override     public String sayHello(String content) {         return "hello, " + content;     } }
public class Test {      public static void main(String[] args) {         HelloService helloService = new HelloServiceImpl();         String msg = helloService.sayHello("world");         // hello world         System.out.println(msg);     } }

但是由于單體服務的諸多弊端,現在很多公司已經將不相關的功能拆分到不同的服務中。

如何像調用本地服務一樣調用遠程服務呢?這時就不得不提RPC框架了(Remote Procedure  Call,遠程過程調用)。他幫我們屏蔽了網絡通信,序列化等操作的實現,真正做到了調用遠程服務和調用本地服務一樣方便。

知名的RPC框架有Spring Cloud,阿里巴巴的Dubbo,Facebook的Thrift,Google grpc等

RPC的調用過程

手寫一個RPC框架的方法教程

一個RPC調用的過程如下

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 調用方發送請求后由代理類將調用的方法,參數組裝成能進行網絡傳輸的消息體

  3. 調用方將消息體發送到提供方

  4. 提供方將消息進行解碼,得到調用的參數

  5. 提供方反射執行相應的方法,并將結果返回

下面我們就分析一下rpc框架是怎么實現的?有哪些地方可以擴展。為了讓大家有一個更形象的認識,我寫了一個github項目,由簡到難實現了一個rpc框架,歡迎star

https://github.com/erlieStar/simple-rpc

生成代理類

前面我們說過,調用方執行方法后,實際上執行的是代理類的方法,代理類幫我們進行序列化和編解碼操作。那么如何生成代理類呢?

我們看一下主流的做法。

Facebook的Thrift和Google的grpc都是定義一個schema文件,然后執行程序,幫你生成客戶端代理類,以及接口。調用方直接用生成的代理類來請求,提供方繼承生成的接口即可。

這種方式最大的優點就是能進行多語言通信,即一份schema文件可以生成Java程序,也可以生成Python程序。調用方是Java程序,提供方是Python程序都能正常進行通訊。而且是二進制協議,通訊效率比較高。

在Java中生成代理類的方式有如下幾種

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. JDK動態代理(實現InvocationHandler接口)

  3. 字節碼操作類庫(如cglib,Javassist)

在Dubbo中提供了2種生成代理類的方式,jdk動態代理和Javassist,默認是javassist,至于原因嗎?當然是javassist的效率更高

協議

為什么需要協議這個東西呢?Spring Cloud是通過Http協議來進行通訊的,那么Dubbo是通過哪種協議來進行通訊的?

為什么需要協議這個東西?

因為數據是以二進制的形式在網絡中傳輸中,RPC的請求數據并不是以一個整體發送到提供方的,而是可能被拆分成多個數據包發送出去,那提供方怎么識別數據呢?

例如一個文本ABCDEF,提供方有可能依次收到的數據為ABC DEF,也有可能為AB CD EF。提供方該怎么處理這些數據呢?

簡單啊,定個規則就可以了。這個規則可以有很多種,這里舉3個例子

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 定長協議,協議內容長度固定,如讀取到50個byte就開始decode操作,可以參考Netty的FixedLengthFrameDecoder

  3. 特殊結束符,定義一個消息結束的分隔符,如讀到\n,表示一個數據讀取完畢了,沒有讀到就一直讀,可以參考Netty的DelimiterBasedFrameDecoder

  4. 變長協議(協議頭+協議體),用一個定長來表示消息體的長度,剩下的內容為消息體,如果你愿意的話,協議頭還會放一些常用的屬性,Http協議的Header就是協議頭,如content-type,content-length等。可以參考Netty的DelimiterBasedFrameDecoder

Dubbo通過自定義協議來進行通訊,協議頭格式如下

手寫一個RPC框架的方法教程

每個位代表的含義如下

手寫一個RPC框架的方法教程

Dubbo為什么要自定義協議,而不用現成的Http協議?

最主要的原因就是自定義協議可以提高性能

Http協議的請求包比較大,有很多無用的內容。自定義協議可以精簡很多內容

Http協議是無狀態的,每次都要重新建立連接,響應完畢后將連接關閉

序列化

協議頭的內容是通過位來表示的,協議體在應用程序中則會被封裝成對象,如Dubbo將請求封裝成Request,將響應封裝成Response

手寫一個RPC框架的方法教程

前面我們說過網絡傳輸的數據必須是二進制數據,但調用方的入參和提供方的返回值都是對象,因此需要序列化和反序列化的過程

序列化的方式有如下幾種

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. JDK原生序列化

  3. JSON

  4. Protobuf

  5. Kryo

  6. Hessian2

  7. MessagePack

我們選擇序列化的方式時,主要考慮如下幾個因素

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 效率

  3. 空間開銷

  4. 通用性和兼容性

  5. 安全性

通訊

常見的IO模型有如下四種

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 同步阻塞IO(Blocking IO)

  3. 同步非阻塞IO(Non-blocking IO)

  4. IO多路復用(IO Multiplexing)

  5. 異步IO(Asynchronous IO)

因為RPC一般用在高并發的場景下,因此我們選擇IO多路復用這種模型,Netty的IO多路復用基于Reactor開發模式來實現,后續的文章我會分析一下這種開發模式是如何支持高并發的

注冊中心

注冊中心的作用和電話簿類似。保存了服務名稱和具體的服務地址之間的映射關系,當我們想和某個服務進行通信時,只需要根據服務名就能查到服務的地址。

更重要的是這個電話簿是動態的,當某個服務的地址改變時,電話簿上的地址就會改變,當某個服務不可用時,電話簿上的地址就會消失

這個動態的電話簿就是注冊中心。

注冊中心的實現方式有很多種,Zookeeper,Redis,Nocas等都可以實現

介紹一下用Zookeeper實現注冊中心的方式

zookeeper有兩種類型的節點,持久節點和臨時節點

當我們往zookeeper上注冊服務的時候,用的是臨時節點,這樣當服務斷開時,節點能被刪除

節點類型解釋
持久節點將節點創建為持久節點,數據會一直存儲在zookeeper服務器上,即使創建該節點的客戶端與服務端的會話關閉了,該節點依然不會被刪除
持久順序節點在持久節點的基礎上增加了節點有序的特性
臨時節點將節點創建為臨時節點,數據不會一直存儲在zookeeper服務器上,當創建該臨時節點的客戶端會話關閉時,該節點在相應的zookeeper服務器上被刪除
臨時順序節點在臨時節點的基礎上增加了節點有序的特性

注冊中心全部掛掉該怎么通信?

當一臺zookeeper掛掉后,會自動切換到另一個zookeeper。全部掛掉也沒有關系,因為dubbo把映射關系保存了一份在本地,這個映射關系可以保存在Map中,也可以保存在文件中

新的服務注冊到注冊中心,本地緩存會更新嗎?

注冊了監聽的話,當然會更新啊。當被監聽的節點或者子節點發生變化的時候,會將相應的內容推送給監聽的客戶端,你就可以更新本地的緩存了

Zookeeper中的事件如下

手寫一個RPC框架的方法教程

你可以把這個監聽理解為分布式的觀察者模式

“手寫一個RPC框架的方法教程”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

太原市| 陆良县| 岚皋县| 台南县| 万全县| 颍上县| 涪陵区| 文昌市| 潼关县| 青海省| 凤城市| 新巴尔虎左旗| 阿尔山市| 洪雅县| 崇明县| 璧山县| 岢岚县| 虹口区| 毕节市| 卢湾区| 康平县| 鸡东县| 常州市| 德清县| 静乐县| 商南县| 古蔺县| 晋江市| 海淀区| 新疆| 阿城市| 榆树市| 灵石县| 报价| 北碚区| 沈阳市| 来凤县| 晋州市| 惠州市| 泰来县| 义马市|