成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何手寫了一個RPC框架

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

 [[349775]]

介紹

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

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

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

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

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

RPC的調用過程

一個RPC調用的過程如下

  1. 調用方發送請求后由代理類將調用的方法,參數組裝成能進行網絡傳輸的消息體
  2. 調用方將消息體發送到提供方
  3. 提供方將消息進行解碼,得到調用的參數
  4. 提供方反射執行相應的方法,并將結果返回

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

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

生成代理類

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

我們看一下主流的做法。

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

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

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

  1. JDK動態代理(實現InvocationHandler接口)
  2. 字節碼操作類庫(如cglib,Javassist)

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

協議

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

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

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

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

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

  1. 定長協議,協議內容長度固定,如讀取到50個byte就開始decode操作,可以參考Netty的FixedLengthFrameDecoder
  2. 特殊結束符,定義一個消息結束的分隔符,如讀到\n,表示一個數據讀取完畢了,沒有讀到就一直讀,可以參考Netty的DelimiterBasedFrameDecoder
  3. 變長協議(協議頭+協議體),用一個定長來表示消息體的長度,剩下的內容為消息體,如果你愿意的話,協議頭還會放一些常用的屬性,Http協議的Header就是協議頭,如content-type,content-length等。可以參考Netty的DelimiterBasedFrameDecoder

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

每個位代表的含義如下

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

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

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

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

序列化

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

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

序列化的方式有如下幾種

  1. JDK原生序列化
  2. JSON
  3. Protobuf
  4. Kryo
  5. Hessian2
  6. MessagePack

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

  1. 效率
  2. 空間開銷
  3. 通用性和兼容性
  4. 安全性

通訊

常見的IO模型有如下四種

  1. 同步阻塞IO(Blocking IO)
  2. 同步非阻塞IO(Non-blocking IO)
  3. IO多路復用(IO Multiplexing)
  4. 異步IO(Asynchronous IO)

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

注冊中心

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

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

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

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

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

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

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

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

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

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

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

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

Zookeeper中的事件如下

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

小結

當然一個成熟的RPC框架還得考慮很多內容,例如路由策略,異常重試,監控,異步調用等,和主流程相關度不大,就不多做介紹了

本文轉載自微信公眾號「Java識堂」,可以通過以下二維碼關注。轉載本文請聯系Java識堂公眾號。

 

責任編輯:武曉燕 來源: Java識堂
相關推薦

2021-02-20 09:45:02

RPC框架Java

2024-08-02 09:49:35

Spring流程Tomcat

2022-03-01 11:38:51

RPC框架后端

2022-03-09 09:43:01

工具類線程項目

2018-09-18 09:38:11

RPC遠程調用網絡通信

2021-03-18 08:04:54

AQS工具CAS

2020-01-09 11:11:35

RPC框架調用遠程

2017-03-02 13:31:02

監控系統

2022-11-07 18:36:03

組件RPC框架

2020-09-09 07:13:05

RPC框架

2024-01-02 12:17:44

Go傳統遠程

2022-04-11 09:15:44

中間件開源

2024-08-01 17:20:55

2020-08-17 08:20:16

iOSAOP框架

2018-08-15 10:51:01

JavaSpring MVC框架

2019-06-17 08:21:06

RPC框架服務

2021-08-12 00:03:37

JSStrview視圖

2021-12-07 06:55:17

節流函數Throttle

2009-10-01 09:19:45

PHP框架ZendFramewoCake

2022-01-26 15:20:00

配置微服務架構
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品视频免费观看 | 日韩免费看视频 | 久久aⅴ乱码一区二区三区 91综合网 | 欧美成人一区二区 | 成人福利在线视频 | 亚洲精品视频在线播放 | 成人久久18免费网站麻豆 | 性国产丰满麻豆videosex | 久久伊人精品 | 一二三四av | 亚洲激情综合网 | 神马福利 | 亚洲精品一区二区三区中文字幕 | 亚洲黄色国产 | 日韩欧美中文字幕在线观看 | 亚洲一区二区精品 | 亚洲精品资源 | 久久99精品久久久久 | 成人久久网 | 午夜欧美 | 国产精品永久免费 | 人人澡人人爱 | 午夜久久久 | 手机av在线 | 国产精品免费观看视频 | 国产精品永久久久久久久www | 久久新视频| 日韩一区二区三区在线观看视频 | 久热电影 | 国产高清在线精品 | 日本 欧美 国产 | 精品久久久久久亚洲精品 | 久久久久久美女 | 97精品一区二区 | 日本亚洲欧美 | 欧美精品电影一区 | 国产乱码精品一区二区三区五月婷 | 亚洲成人精品久久久 | 国产精品久久久久久久久免费相片 | 瑞克和莫蒂第五季在线观看 | 色啪网 |