1. 程式人生 > >Dubbo原始碼解析(一)服務發現

Dubbo原始碼解析(一)服務發現

一、原始碼模組

官網地址

原始碼地址

1.1 原始碼模組組織

Dubbo工程是一個Maven多Module的專案,以包結構來組織各個模組。

 

核心模組及其關係,如圖所示:

1.2 模組說明

  • 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 容器模組,是一個Standalone的容器,以簡單的Main類載入Spring啟動,因為服務通常不需要Tomcat/JBoss等Web容器的特性,沒必要用Web容器去載入服務。因為服務通常不需要 Tomcat/JBoss 等 Web 容器的特性,沒必要用 Web 容器去載入服務。

 

二、服務發現

Dubbo的應用會在啟動時完成服務註冊或訂閱(不論是生產者,還是消費者)如下圖所示。

  • 圖中小方塊Protocol, Cluster, Proxy, Service, Container, Registry, Monitor代表層或模組,藍色的表示與業務有互動,綠色的表示只對Dubbo內部互動。
  • 圖中背景方塊Consumer, Provider, Registry, Monitor代表部署邏輯拓普節點。
  • 圖中藍色虛線為初始化時呼叫,紅色虛線為執行時非同步呼叫,紅色實線為執行時同步呼叫。
  • 圖中只包含RPC的層,不包含Remoting的層,Remoting整體都隱含在Protocol中。

 

2.1 多種啟動方式

除了XML方式,Dubbo的服務Config還支援多種方式,包括

  • 註解驅動(Annotation-Driven)
  • 外部化配置(External Configuration)
  • 以及自動裝配(Auto-Configure)

具體的可以參考 http://dubbo.apache.org/zh-cn/blog/dubbo-annotation.html

下面我們的分析以最基礎也是應用最廣泛的Spring配置方式為例。

 

2.2 配置資訊

在配置檔案中,所有dubbo的標籤,都統一用DubboBeanDefinitionParser進行解析,基於一對一屬性對映,將XML標籤解析為Bean物件。

相關資訊可以參考: Dubbo中對Spring配置標籤擴充套件(http://www.cnblogs.com/ghj1976/p/5379332.html

以 dubbo-demo-provider 為例, 它的配置檔案如下:

  • com.alibaba.dubbo.demo.provider.DemoServiceImpl 是服務實現類。
  • com.alibaba.dubbo.demo.DemoService 是服務需要實現的介面。

2.3 配置檔案的解析過程

  • 基於dubbo.jar內的META-INF/spring.handlers配置,Spring在遇到dubbo名稱空間時,會回撥DubboNamespaceHandler。
  • 所有dubbo的標籤,都統一用DubboBeanDefinitionParser進行解析,基於一對一屬性對映,將XML標籤解析為Bean物件。

每個service方法的配置會解析成對應的 com.alibaba.dubbo.config.spring.ServiceBean<T> 類的例項。

 

2.4 服務註冊和引用

在Bean物件例項化的過程中,參考Spring Bean物件的生命週期,依次實現了不同的方法完成註冊和引用。

關於Spring物件的生命週期,可以參考 https://www.cnblogs.com/zrtqsk/p/3735273.html

在 afterPropertiesSet 後, 會呼叫到 ServiceConfig.export() ,具體的呼叫棧如下

&n