1. 程式人生 > 其它 >dubbo原理及原始碼剖析

dubbo原理及原始碼剖析

一、架構整體設計

1.Dubbo呼叫關係說明

在這裡主要由四部分組成:

Provider: 暴露服務的服務提供方
Protocol 負責提供者和消費者之間協議互動資料
Service 真實的業務服務資訊 可以理解成介面和實現
Container Dubbo的執行環境
Consumer: 呼叫遠端服務的服務消費方
Protocol 負責提供者和消費者之間協議互動資料
Cluster 感知提供者端的列表資訊
Proxy 可以理解成 提供者的服務呼叫代理類 由它接管 Consumer中的介面呼叫邏輯
Registry: 註冊中心,用於作為服務發現和路由配置等工作,提供者和消費者都會在這裡進行註冊
Monitor: 用於提供者和消費者中的資料統計,比如呼叫頻次,成功失敗次數等資訊。
啟動和執行流程說明:
提供者端啟動 容器負責把Service資訊載入 並通過Protocol 註冊到註冊中心
消費者端啟動 通過監聽提供者列表來感知提供者資訊 並在提供者發生改變時 通過註冊中心及時通知消費端
消費方發起 請求 通過Proxy模組
利用Cluster模組 來選擇真實的要傳送給的提供者資訊
交由Consumer中的Protocol 把資訊傳送給提供者
提供者同樣需要通過 Protocol 模組來處理消費者的資訊
最後由真正的服務提供者 Service 來進行處理
2.整體的呼叫鏈路

說明 淡綠色代表了 服務生產者的範圍 淡藍色 代表了服務消費者的範圍 紅色箭頭代表了呼叫的方向
業務邏輯層 RPC層(遠端過程呼叫) Remoting (遠端資料傳輸)
整體鏈路呼叫的流程:
1. 消費者通過Interface進行方法呼叫 統一交由消費者端的 Proxy 通過ProxyFactory 來進行代理物件的建立 使用到了 jdk javassist技術
2.交給Filter 這個模組 做一個統一的過濾請求 在SPI案例中涉及過
3.接下來會進入最主要的Invoker呼叫邏輯
通過Directory 去配置中新讀取資訊 最終通過list方法獲取所有的Invoker
通過Cluster模組 根據選擇的具體路由規則 來選取Invoker列表
通過LoadBalance模組 根據負載均衡策略 選擇一個具體的Invoker 來處理我們的請求
如果執行中出現錯誤 並且Consumer階段配置了重試機制 則會重新嘗試執行
4. 繼續經過Filter 進行執行功能的前後封裝 Invoker 選擇具體的執行協議
5. 客戶端 進行編碼和序列化 然後傳送資料
6. 到達Consumer中的 Server 在這裡進行 反編碼 和 反序列化的接收資料
7. 使用Exporter選擇執行器
8. 交給Filter 進行一個提供者端的過濾 到達 Invoker 執行器
9. 通過Invoker 呼叫介面的具體實現 然後返回

 二、服務註冊與消費

1.服務的註冊過程分析

首先 ServiceConfig 類拿到對外提供服務的實際類 ref(如:HelloServiceImpl),然後通過ProxyFactory 介面實現類中的 getInvoker 方法使用 ref 生成一個 AbstractProxyInvoker 例項,到這一步就完成具體服務到 Invoker 的轉化。接下來就是 Invoker 轉換到 Exporter 的過程。

Invoker 轉換成 Exporter的過程
其中會涉及到 RegistryService介面 RegistryFactory 介面 和 註冊provider到註冊中心流程的過程
(1)RegistryService程式碼解讀,這塊兒的程式碼比較簡單,主要是對指定的路徑進行註冊,解綁,監聽和取消監聽,查詢操作。也是註冊中心中最為基礎的類。
(2)我們再來看 RegistryFactory ,是通過他來生成真實的註冊中心。通過這種方式,也可以保證一個應用中可以使用多個註冊中心。可以看到這裡也是通過不同的protocol引數,來選擇不同的協議。
(3)下面我們就來跟蹤一下,一個服務是如何註冊到註冊中心上去的。其中比較關鍵的一個類是RegistryProtocol ,他負責管理整個註冊中心相關協議。並且統一對外提供服務。這裡我們主要以RegistryProtocol.export 方法作為入口,這個方法主要的作用就是將我們需要執行的資訊註冊並且匯出。
(4)下面我們再來看看 register 方法, 這裡面做的比較簡單,主要是從 RegistoryFactory 中獲取註冊中心,並且進行地址註冊。
(5)這裡我們再跟裡面的register方法之前,先來介紹一下Registry中的類目錄結構
+- RegistryService
| +- Registry
| | +- AbstractRegistry
| | | +- FailbackRegistry
| | | | +- ZookeeperRegistry
| | | | +- NacosRegistry
| | | | +- ...
目錄結構描述如下:
在這裡每個層級代表繼承自父級
這裡面 RegistryService 就是我們之前所講對外提供註冊機制的介面。
其下面 Registry 也同樣是一個介面,是對 RegistryService 的整合,並且繼承了 Node 介面,說明註冊中心也是基於URL去做的。
AbstractRegistry 是對註冊中心的封裝,其主要會對本地註冊地址的封裝,主要功能在於遠端註冊中心不可用的時候,可以採用本地的註冊中心來使用。
FailbackRegistry 從名字中可以看出來,失敗自動恢復,後臺記錄失敗請求,定時重發功能。
最深的一層則更多是真實的第三方渠道實現。
(6)下面我們來看一下在 FailbackRegistry 中的實現, 可以在這裡看到他的主要作用是呼叫第三方的實現方式,並且在出現錯誤時增加重試機制。
(7)下面我們再來看看Zookeeper中 doRegister 方法的實現, 可以看到這裡的實現也比較簡單,關鍵在於 toUrlPath 方法的實現。關於 dynamic 的值,我們也在上面有看到,他的URL也是true的。
(8)解讀 toUrlPath 方法。可以看到這裡的實現也是比較簡單,也驗證了我們之前的路徑規則。