Dubbo架構深刻篇----RPC實現總結

最近我拜讀了mindwind的一片博客文章深刻淺出 RPC - 深刻篇,但願經過Dubbo深刻學習RPC架構設計,在此結合RPC架構的原理,解析Dubbo是如何實現RPC架構的。html

RPC架構模型

RPC架構的主要目的是在構建分佈式系統時,調用遠程方法就如同調用本地方法同樣方便快捷,簡化開發,提升效率。java

咱們看看下面這張圖,瞭解一下RPC架構的主要組成部分及調用關係:apache

image

以上圖片引自mindfloating的博客

上圖左側是調用者,右側是方法提供端。咱們分別解釋一下上圖的各模塊的職責:json

從左側開始,Caller是調用者;RpcClient是Rpc協議定義的客戶端,包括遠程接口的地址列表及調用方式的信息等,Caller導入RpcClient;RemoteAPI表示遠程接口;RpcProxy是一個對遠程方法調用的代理組件,封裝了遠程過程調用的細節,能夠包括加載地址列表,尋址,調用集羣模塊實現負載均衡、高可用,查找調用信息,調用RpcInvoker等;RpcInvoker是具體的RemoteAPI的調用者封裝對象,它包含了一個具體接口方法的地址、調用方式等信息,並提供了調用處理方法;RpcConnector負責封裝實現網絡通訊細節,如創建會話通道,發送數據請求和接收返回值數據;RpcProtocol是Rpc協議規範,定義了數據序列化和反序列化方法,如何解析地址信息等細節。網絡

右側爲接口服務端,RpcAcceptor相似RpcConnector,封裝實現網絡通訊細節,接收請求數據,發送本地接口處理後的返回值給客戶端;RpcProcessor負責線程池管理,發起本地方法調用等;服務端RpcInvoker是本地API的調用者,經過反射技術調用指定接口的方法;Callee是服務端的本地接口類,導出RPC服務爲RpcServer,客戶端Caller將其做爲RpcClient導入.架構

咱們按照以上RPC的調用流程和各組件職責,聊一聊Dubbo是如何實現的。負載均衡

Dubbo的RPC架構實現

Dubbo的調用關係以下圖所示,以註冊中心Registry爲中心,Provider即服務提供者,將服務export出來註冊(一、register)存儲到Registry,Consumer即客戶端調用者,從Registry訂閱所關心的服務(二、subscribe),首次訂閱時拉取訂閱服務全部的地址列表(服務提供者註冊到Registry上的信息),當訂閱服務有更新(地址變動或有新的地址註冊加入),Consumer收到註冊中心的服務更新通知(三、notify),以上是服務端export的過程。分佈式

客戶端發起RPC調用時,首先從服務地址列表裏refer()指定的服務,這其中有服務尋址和從集羣中篩選最終指向一個服務的過程,這就是import的過程。獲得某個服務指向,則發起遠程調用(四、invoke)。ide

image

以上圖片引自Dubbo官方用戶手冊

那麼Dubbo具體是如何實現RPC的整個過程的呢?對應RPC模型,Dubbo相應的組件又是如何實現和交互的?下圖展現了Dubbo整個設計思路。學習

image

以上圖片引自Dubbo官方用戶手冊

圖例說明:

  • 圖中左邊淡藍背景的爲服務消費方使用的接口,右邊淡綠色背景的爲服務提供方使用的接口,位於中軸線上的爲雙方都用到的接口。
  • 圖中從下至上分爲十層,各層均爲單向依賴,右邊的黑色箭頭表明層之間的依賴關係,每一層均可以剝離上層被複用,其中,Service 和 Config 層爲 API,其它各層均爲 SPI。
  • 圖中綠色小塊的爲擴展接口,藍色小塊爲實現類,圖中只顯示用於關聯各層的實現類。
  • 圖中藍色虛線爲初始化過程,即啓動時組裝鏈,紅色實線爲方法調用過程,即運行時調時鏈,紫色三角箭頭爲繼承,能夠把子類看做父類的同一個節點,線上的文字爲調用的方法。

接下來咱們對應RPC架構模型的組件談談Dubbo的設計。

export和import

Dubbo服務端接口export(導出)是將接口信息註冊到註冊中心Registry的過程。而客戶端import(導入)遠程接口是經過從註冊中心Registry訂閱遠程服務接口,收到通知後拉取到本地的過程。
註冊和訂閱的過程,不須要修改服務端本地的類和方法,只需保證客戶端和服務端共同引用一個包含接口的jar包。服務端和客戶端分別編寫簡單的dubbo接口配置xml文件(或註解的方式),容器啓動時就自動註冊和訂閱了。

客戶端調用的過程

看上圖Config層的橙色小圓點,紅色實線剪頭爲調用鏈。客戶端invoke遠程API(Interface),實際是調用了Proxy層的RpcProxy,proxy又調用集羣組件Cluster,從集羣中篩選出一個Invoker做爲調用者發起調用。

咱們看到,在Cluster層中篩選的過程調用了Directory(實現類爲RegistryDirectory)、Router、LoadBalance,分別經過Directory實現了服務的高可用,經過Router實現了智能路由功能,經過LoadBalance實現了負載均衡。

從集羣模塊中篩選出一個Invoker後執行invoke()方法執行方法調用,到了Protocol協議層,通過Filter組件作攔截過濾處理,如用戶名、密碼驗證等可在此處理。過濾經過後,調用Protocol實現類如DubboProtocol或HessianProtocol等的invoke()方法。

具體的協議實現類(如DubboProtocol)會請求ExchangeClient組件,它封裝了具體的數據通信細節,是底層數據通訊的代理層。所以它天然會調用底層的通訊組件(默認是Netty)實現Client創建鏈接、Server綁定端口和數據傳輸(request、return)的功能。

數據傳輸前須要數據序列化,服務端接收到數據須要反序列化,這些都靠序列化組件實現。Codec是序列化組件的代理層,具體序列化協議,默認是Hessian,還可選擇Kryo,Thrift(被Dubbo改造,與原Thrift不兼容),dubbo, hessian2, java, json等,具體參見Dubbo用戶手冊

服務端調用

服務端接收到客戶端的請求後,反序列化數據,經過DubboHandler協議處理請求,找到註冊的本地Exporter,觸發invoke(),通過過濾器處理後,調用Invoker代理層,觸發真正的本地接口調用,返回數據序列化後發送給客戶端。

以上內容以RPC模型爲基礎,分析總結了Dubbo實現RPC的大致流程,後續我還會分別針對某些組件展開討論Dubbo的設計實現。

相關文章
相關標籤/搜索