文章目錄
-
-
- 一、Cluster層
- 二、Protocol 層
-
- 1.ConsumerContextFilter 的invoke 方法
- 2.FutureFilter 的invoke 方法
- 3.MonitorFilter中的invoke方法
- 4.DubboInvoker中invoke方法
-
消費端代碼示例(參考incubator-dubbo源碼中dubbo-demo子產品):
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
context.start();
DemoService demoService = (DemoService) context.getBean("demoService”);
// 調用遠端方法
String hello = demoService.sayHello("world");
System.out.println(hello);
以dubbo分層概念來了解消費端調用過程:

服務端啟動後,消費端引用服務端的接口類會生成一個代理類,即生成InvokerInvocationHandler(invoker)對象執行個體,是以在調用的時候,會直接調用 InvokerInvocationHandler 的 invoke 方法,
一、Cluster層
Cluster層作用:封裝多個提供者的路由及負載均衡,并橋接注冊中心,以Invoker為中心,擴充接口為Cluster、Directory、Router和LoadBalance。将多個服務提供方組合為一個服務提供方,實作對服務消費方來透明,隻需要與一個服務提供方進行互動。
根據 https://blog.csdn.net/zhuqiuhui/article/details/84075521 分析知這裡的 invoker 是 MockClusterInvoker 執行個體,即會調用 MockClusterInvoker 的invoke方法,該方法首先判斷directory中的url是否含有mock值的設定,若沒有設定預設值false。這裡的directory中的url的變量是:
Debug,如下:
其中 this.invoker變量值如下:
上面會調用FailOverClusterInvoker.invoke(),即會調用其父類AbstractClusterInvoker.invoke()的方法。如下:
Debug-1:
Debug-1 分成以下幾個過程:
1. 檢查RPC Cluster invoker中要執行的接口是否被銷毀,若銷毀,則抛出異常。
2. 在調用提供者之前,會擷取目前線程臨時變量裡的RpcContext對象,再将RpcContext對象裡的參數設定到Invocation對象。
RpcContext 是一個臨時狀态持有者,每當發請求或者收到請求的時候RpcContext都會發生變化。例如A調用B,然後B調用C,在服務B中,在B調用C之前,RpcContext儲存了A調用B的參數。當B調用C的時候,RpcContext儲存了B調用C的參數。從源碼上看RpcContext對象是綁定線上程臨時變量LOCAL上,是以可以通過線程臨時變量來擷取到RpcContext的相關參數值。
3. 列出所有的Invoker
這裡可以看到 directory執行個體是 RegistryDirectory 的執行個體,會調用其父類的list方法,即如下:
上面走到RegistryDirectory的doList方法中,其中RegistryDirectory是在消費端服務啟動過程中自動會生成RegistryDirectory執行個體,對應的屬性也初始化完成了,即在消費端啟動過程時,把方法和對應的invoker關系存放到了RegistryDirectory中的methodInvokerMap屬性中(參考:https://blog.csdn.net/zhuqiuhui/article/details/84075521),是以這裡,如下:
其中傳回的 invokers 清單如上面的變量。
4. 擷取方法上配置的負載均衡政策,若沒有配置,選擇預設的政策
常用的配置方法如下:
<dubbo:reference interloadbalance="roundrobin"/>
這裡傳回的 loadbalance 的執行個體是 RandomLoadBalance 的執行個體。
5. 幂等操作,即在異步操作中會預設加上invocation ID,不作分析
6. 方法調用
會走到 FailOverClusterInvoker 中的 doInvoke 方法中,即:
該方法首先使用負載均衡政策選擇合适的invoker(不再分析),然後再進行invoker調用,其中invoker變量如下:
上面變量的第一行可以看出 invoker 執行個體是InvokerDelegate執行個體對象,調用其invoke方法會走到InvokerWrapper的invoke方法,由于InvokerDelegate執行個體對象中的invoker内部屬性是 Invoker 接口的匿名實作,其泛型是ProtocolFilterWrapper類,即如上圖中的”[email protected]”,是以會調用”[email protected]”執行個體invoke方法,看其内部實作:
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
調用的是filter的invoke方法(其中的filter執行個體是ConsumerContextFilter執行個體),首先會調用 ConsumerContextFilter 的 invoke 方法,在ConsumerContextFilter 的 invoke 方法中再調用 FutureFilter 的invoke方法,最後在 FutureFilter 的invoke方法中調用 MonitorFilter 的 invoke 方法,MonitorFilter 的 invoke 方法中會調用DubboInvoker 的invoke方法。
二、Protocol 層
Protocol層作用:封裝RPC調用,以Invocation和Result為中心,擴充接口為Protocol、Invoker和Exporter。Protocol是服務域,它是Invoker暴露和引用的主功能入口,它負責Invoker的生命周期管理。Invoker是實體域,它是Dubbo的核心模型,其它模型都向它靠擾,或轉換成它,它代表一個可執行體,可向它發起invoke調用,它有可能是一個本地的實作,也可能是一個遠端的實作,也可能一個叢集實作。
1.ConsumerContextFilter 的invoke 方法
這裡首先對 RpcContext 進行資訊設定,其後清空sever上下文,再對調用後的結果進行後處理(即postProcessResult方法,主要設定一些要傳遞的參數),在finally中清空了傳遞的參數(目的為下一次調用做準備)。postProcessResult參數中的invoker調用invoke方法會繼續調用下一個filter中的invoke方法,即FutureFilter中的invoke方法。從上面過程可以看出主要對 RpcContext 内容進行設定。
2.FutureFilter 的invoke 方法
主要做一些異步回調工作,其中 invoker.invoke方法會調用MonitorFilter中的invoke方法
3.MonitorFilter中的invoke方法
MonitorFilter會做下監控的處理。會調用 DubboInvoker中invoke方法。
4.DubboInvoker中invoke方法
走完上述方法就完成整個方法的調用過程。