1. 前言
在 Dubbo 框架中,服務消費者通過 XML 配置方式引用服務時,涉及多個模塊之間的協作。
不放dubbo官方的設計圖了,這裏同樣放一張自己畫的服務消費者調用圖,後面的介紹也是圍繞這張圖來的。
以下是服務消費者引用服務時,各個模塊之間的源碼方法調用關係的詳細説明。
2. 簡述過程
在 dubbo-config-spring 項目模塊中,dubbo 框架定義了 dubbo.xsd。業務使用時,可以基於 定義好的標籤(<dubbo:reference>等),在 xml 中配置要發佈的服務。
這部分內容可以查看前面寫的 《Spring XML自定義命名空間》。
服務提供者在啓動時,DubboNamespaceHandler 中會根據 XML 配置中的 <dubbo:reference> 標籤引用服務,整個過程大致如下:
-
解析 XML 配置:
- 解析
<dubbo:reference>標籤,創建ReferenceConfig對象。
- 解析
-
服務引用:
- 調用
ReferenceConfig.get()方法,開始服務引用過程。
- 調用
-
協議引用:
ReferenceConfig.get()方法內部調用Protocol.refer()方法,通過具體的協議實現服務的引用。
-
服務發現和負載均衡:
- 通過
Registry和Directory進行服務發現,並通過Cluster和LoadBalance實現負載均衡。
- 通過
-
代理創建:
- 使用
ProxyFactory創建服務接口的代理對象。
- 使用
3. ReferenceConfig 模塊
- 作用:負責服務引用的配置和管理,是服務引用的入口。
- 關鍵方法:
ReferenceConfig.get()
public class ReferenceConfig<T> {
private volatile T ref;
public synchronized T get() {
if (ref == null) {
init();
}
return ref;
}
private void init() {
// 調用 Protocol.refer()
Invoker<?> invoker = protocol.refer(interfaceClass, url);
// 創建代理對象
ref = proxyFactory.getProxy(invoker);
}
}
4. Protocol 模塊
- 作用:負責服務的導出和引用。
- 關鍵方法:
Protocol.refer()
public interface Protocol {
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}
5. RegistryProtocol.refer()
- 作用:處理服務發現和引用相關的邏輯。
-
調用關係:
- 獲取註冊中心:通過
RegistryFactory獲取Registry實例。 - 創建服務目錄:創建
RegistryDirectory,用於管理服務提供者的地址列表。 - 訂閲服務:通過
Registry訂閲服務提供者信息。 - 集羣合併:通過
Cluster.join()將多個服務提供者的Invoker合併為一個集羣Invoker。
- 獲取註冊中心:通過
public class RegistryProtocol implements Protocol {
@Override
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 1. 獲取註冊中心
Registry registry = registryFactory.getRegistry(url);
// 2. 創建服務目錄
RegistryDirectory<T> directory = new RegistryDirectory<>(type, url);
// 3. 訂閲服務提供者
directory.setRegistry(registry);
directory.subscribe(subscribeUrl);
// 4. 返回集羣 Invoker
return cluster.join(directory);
}
}
6. Cluster 模塊
- 作用:負責將多個服務提供者的
Invoker合併為一個集羣Invoker,實現負載均衡和容錯。 - 關鍵方法:
Cluster.join()
public interface Cluster {
<T> Invoker<T> join(Directory<T> directory) throws RpcException;
}
7. Invoker 模塊
- 作用:表示一個可調用的服務引用,是服務調用的核心模型。
- 關鍵方法:
Invoker.invoke()用於執行遠程調用。
public interface Invoker<T> {
Result invoke(Invocation invocation) throws RpcException;
}
8. ProxyFactory 模塊
- 作用:負責創建服務接口的代理對象。
- 關鍵方法:
ProxyFactory.getProxy()
public interface ProxyFactory {
<T> T getProxy(Invoker<T> invoker) throws RpcException;
}
9. LoadBalance 模塊
- 作用:提供負載均衡策略,選擇合適的
Invoker進行調用。 - 關鍵方法:
LoadBalance.select()
public interface LoadBalance {
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
}
10. 總結
在 Dubbo 服務消費者的引用過程中,多個模塊協同工作:
- ReferenceConfig:負責服務引用的配置和入口。
- Protocol 和 Invoker:負責服務的引用和調用。
- Registry 和 Directory:負責服務的發現和動態管理。
- Cluster 和 LoadBalance:負責負載均衡和容錯。
- ProxyFactory:負責創建服務接口的代理對象。
圖示化流程
ReferenceConfig.get()
└── RegistryProtocol.refer()
└── Registry.getRegistry()
└── RegistryDirectory.subscribe()
└── Cluster.join()
└── LoadBalance.select()
└── ProxyFactory.getProxy()
-
ReferenceConfig.get():
- 解析服務引用配置,準備服務引用。
- 調用
Protocol.refer()進行服務引用。
-
RegistryProtocol.refer():
- 獲取註冊中心並創建服務目錄。
- 訂閲服務提供者信息。
- 通過
Cluster.join()返回集羣 Invoker。
-
Cluster.join():
- 合併多個服務提供者的
Invoker,實現負載均衡。
- 合併多個服務提供者的
-
ProxyFactory.getProxy():
- 創建服務接口的代理對象,供消費者使用。
-
LoadBalance.select():
- 在服務調用時,選擇合適的
Invoker進行調用。
- 在服務調用時,選擇合適的