程式碼架構
整體設計
圖示
- 圖中左側淺藍色背景是服務消費者使用的介面,右側淺綠色背景是服務提供者使用的介面,中軸線上的介面是雙方都使用的介面。
- 圖中由下至上分為十層,每一層單向依賴,右側黑色箭頭代表層級間的依賴關係。每一層剝離上層後可重複使用。其中,Service 和 Config 層是 API,其他層都是 SPI。
- 圖中小綠色塊是擴充介面,小藍色塊是實作類別。圖中僅展示用於關聯每一層的實作類別。
- 圖中藍色虛線是初始化流程,即啟動時的組裝鏈,紅色實線是方法呼叫流程,即執行時期的呼叫鏈,紫色三角箭頭是繼承關係。可以將子類別視為父類別的同一個節點,線上方的文字是要呼叫的方法。
每一層說明
- Config 組態層:對外組態介面,以
ServiceConfig
、ReferenceConfig
為中心,可以直接初始化組態類別,或者透過 Spring 解析組態生成組態類別。 - Proxy 服務代理層:服務介面透明代理,生成服務客戶端 Stub 和伺服器端 Skeleton,以
ServiceProxy
為中心,擴充介面為ProxyFactory
。 - Registry 註冊中心層:封裝服務地址的註冊與發現,以服務 URL 為中心,擴充介面為
RegistryFactory
、Registry
、RegistryService
。 - 叢集路由層:封裝多個提供者的路由和負載均衡,並橋接註冊中心,以
Invoker
為中心,擴展接口為Cluster
、Directory
、Router
、LoadBalance
- 監控層:RPC 調用次數和調用時間監控,以
Statistics
為中心,擴展接口為MonitorFactory
、Monitor
、MonitorService
- 協定遠程調用層:封裝 RPC 調用,以
Invocation
、Result
為中心,擴展接口為Protocol
、Invoker
、Exporter
- 信息交換層:封裝請求響應模式,同步轉異步,以
Request
、Response
為中心,擴展接口為Exchanger
、ExchangeChannel
、ExchangeClient
、ExchangeServer
- 網路傳輸層:抽象 mina 和 netty 為統一接口,以
Message
為中心,擴展接口為Channel
、Transporter
、Client
、Server
、Codec
- 數據序列化層:一些可複用的工具,擴展接口為
Serialization
、ObjectInput
、ObjectOutput
、ThreadPool
關係說明
- 在 RPC 中,Protocol 是核心層,也就是說,只要有 Protocol + Invoker + Exporter,就能完成非透明的 RPC 調用,然後在 Invoker 的主流程上 Filter 攔截點。
- 圖中的 Consumer 和 Provider 是抽象概念,只是為了讓看者更容易理解哪些類屬於客戶端和服務器端。不用 Client 和 Server 的原因是 Dubbo 在很多場景中都會用到 Provider、Consumer、Registry、Monitor 劃分邏輯拓撲節點,維持統一概念。
- Cluster 是外圍概念,所以 Cluster 的目的是將多個 Invoker 偽裝成一個 Invoker,這樣其它人只需要關注 Protocol 層 Invoker 即可。加入 Cluster 或移除 Cluster 對其它層次都不會影響,因為只有一個 Provider,是不需要 Cluster 的。
- Proxy 層封裝了所有接口的透明代理,而在其它層都是以 Invoker 為中心,只有到了暴露給用戶使用時,才用 Proxy 將 Invoker 轉換為接口,或將接口實現轉換為 Invoker,也就是去掉 Proxy 層 RPC 是可以 Run 的,只是不那麼透明,並且也不像是調用本地服務一樣調用遠程服務。
- Remoting 實現是 Dubbo 協議的實現,如果你選擇了 RMI 協議,整個 Remoting 都不会用上,Remoting 內部再劃為 Transport 傳輸層和 Exchange 信息交換層,Transport 層只負責單向消息傳輸,Netty,Grizzly 的抽象,它也可以擴展 UDP 傳輸,而 Exchange 層是在傳輸層之上封裝了 Request-Response 語義。
- Registry 和 Monitor 實際上不算一層,而是一個獨立的節點,只是為了全局概覽,用層的方式畫在一起。
模塊子包
模塊說明
- dubbo-common 公共邏輯模塊:包含 Util 類和公共模型。
- dubbo-remoting 遠程通信模塊:相當於 Dubbo 協議的實現,如果 RPC 用 RMI 協議則不需要使用此包。
- dubbo-rpc 遠程調用模塊:抽象各種類型的協議以及動態代理,只包含一對一調用,不關心集群管理。
- dubbo-cluster 集群模塊:將多個服務提供者偽裝成一個提供者,包括:負載均衡、容錯、路由等,集群的地址列表可以是靜態配置的,也可以是由註冊中心下發。
- dubbo-registry 註冊中心模塊:基於註冊中心下發地址的集群方式,以及對多種註冊中心的抽象。
- dubbo-monitor 監控模塊:統計服務調用次數、調用時間以及調用鏈跟蹤服務。
- dubbo-config 設定模組:Dubbo 的對外 API,使用者透過 Config 使用 Dubbo,隱藏了 Dubbo 所有細節。
- dubbo-container 容器模組:這是一個獨立容器,載入一個簡單的 Main 啟動 Spring,因為服務通常不需要 Tomcat/JBoss 等 Web 容器的功能,所以沒必要使用 Web 容器來載入服務。
整體上按階層結構進行分包。與分層的區別是
- Container 是一個服務容器,用於部署和運行服務,在分層中沒有體現出來。
- Protocol 層和 Proxy 層都被放在 rpc 模組中,這兩層是 rpc 的核心,在不需要叢集的情況下,也就是只有一個 provider 時,可以只使用這兩層完成 rpc 調用。
- Transport 層和 Exchange 層都被放在 remoting 模組中,是 rpc 調用的通訊基礎。
- Serialize 層被放在 common 模組中,以便更大程度的複用。
依賴關係
圖示
- 圖中 Protocol、Cluster、Proxy、Service、Container、Registry、Monitor 代表階層或模組,藍色表示與業務互動,綠色只在 Dubbo 內部互動。
- 圖中背景方塊 Consumer、Provider、Registry、Monitor 代表部署邏輯拓撲節點。
- 圖中藍色虛線是初始化時調用,紅色虛線是運行時非同步調用,紅色實線是運行時同步調用。
- 圖中只包含了 RPC 層,不包含 Remoting 層,Remoting 作為一個整體,隱含在 Protocol 中。
調用鏈
將總體設計圖的紅色調用鏈展開,如下圖所示
暴露服務時序
將總體設計圖右側服務提供者暴露服務的藍色初始化鏈展開,時序圖如下所示
參考服務時序
將總體設計圖左側服務消費者參考服務的綠色初始化鏈展開,時序圖如下所示
領域模型
在 Dubbo 的核心領域模型中
- Protocol 是服務領域,它是 Invoker 暴露和參考的主要功能入口,負責 Invoker 的生命週期管理。
- Invoker 是一個實體域,它是 Dubbo 的核心模型,其他模型都向它靠攏,或轉換成它,它代表一個可執行體,可對其發起 invoke 調用,它有可能是一個本機實現,也可能是一個遠端實現,也可能是一個叢集實現。
- Invocation 是一個會話域,它持有調用過程中的變數,例如方法名,參數等。
基本設計原則
- 採用微核心 + 插件模式,微核心只負責組裝插件,Dubbo 自身的功能也是透過擴展點實現的,也就是 Dubbo 的所有功能點都可以被使用者自定義的擴展替換。
- 使用 URL 作為統一的配置資訊格式,所有擴展點都透過傳遞 URL 攜帶配置資訊。
上次修改時間 2023 年 1 月 2 日:增強英文文件 (#1798) (95a9f4f6c1c)