dubbo 請求調用過程分析

服務消費方發起請求

當服務的消費方引用了某遠程服務,服務的應用方在spring的配置實例如下:

<dubbo:referenceid="demoService"interface="com.alibaba.dubbo.demo.DemoServ ice" />

demoService實例其實是代理工廠生產的代理對象(大家可以參考代理那部分生成的僞代碼),在代碼中調用demoService.sayHello(“world!”)時,

1.      將方法名方法參數傳入InvokerInvocationHandler的invoke方

對於Object中的方法toString, hashCode, equals直接調用invoker的對應方法,

這裏對於Object的方法需要被遠程調用嗎?調用了是不是報錯比默認處理更好呢??

遠程調用層是以Invocation, Result爲中心, 這裏根據要調用的方法以及傳入的參數構建RpcInvocation對象,作爲Invoker的入參

2.      MockClusterInvoker根據參數提供了三種調用策略

不需要mock, 直接調用FailoverClusterInvoker

強制mock,調用mock

先調FailoverClusterInvoker,調用失敗在mock、

3.      FailoverClusterInvoker默認調用策略

通過目錄服務查找到所有訂閱的服務提供者的Invoker對象

路由服務根據策略來過濾選擇調用的Invokers

通過負載均衡策略LoadBalance來選擇一個Invoker

4.      執行選擇的Invoker.inoker(invocation)

經過監聽器鏈,默認沒有

經過過濾器鏈,內置實現了很多

執行到遠程調用的DubboInvoker

5.      DubboInvoker

根據url 也就是根據服務提供者的長連接,這裏封裝成交互層對象ExchangeClient供這裏調用

判斷遠程調用類型同步,異步還是oneway模式

ExchangeClient發起遠程調用,底層remoting不在這裏描述了

獲取調用結果:

        Oneway返回空RpcResult

        異步,直接返回空RpcResult, ResponseFuture回調

        同步, ResponseFuture模式同步轉異步,等待響應返回

 

服務提供方接收調用請求

同樣我們也是rpc調用層DubboProtocol層開始分析,對於通信層remoting的數據接收反序列等等過程不做分析。

DubboProtocol的requestHandler是ExchangeHandler的實現,是remoting層接收數據後的回調。

requestHandler.replay方法接收請求消息,這裏只處理遠程調用消息Invocation。

1.      通過Invocation獲取服務名和端口組成serviceKey=com.alibaba.dubbo.demo.DemoService:20880, 從DubboProtocol的exproterMap中獲取暴露服務的DubboExporter, 在從dubboExporter 獲取invoker返回

2.      經過過濾器鏈

3.      經過監聽器鏈

4.      到達執行真正調用的invoker, 這個invoker由代理工廠ProxyFactory.getInvoker(demoService, DemoService.class, registryUrl)創建,具體請看代理那部分介紹。

調用demoService實例方法,將結果封裝成RpcResult返回

5.      交換層構建Response,通過Remoting層編碼傳輸將結果響應給調用方

 

服務消費方發起遠程調用的底層通信


 

服務提供方接收請求並響應的底層通信



一:provider提供方




ClassPathXmlApplicationContext <init>(構造方法)
-> ClassPathXmlApplicationContext refresh()
-> ClassPathXmlApplicationContext finishRefresh()
-> AbstractApplicationContext publishEvent()
-> ServiceBean onApplicationEvent()
-> ServiceConfig doExport()
#構造dubbo對象 application provider module protocol registry service reference consume等

-> ServiceConfig doExportUrls #導出URL,獲取註冊中心RegistryConfig
#註冊中心:registry://10.199.101.228:2181/com.alibaba.dubbo.registry.RegistryService?application=demo&backup=10.199.101.227:2181,10.199.101.229:2181&dubbo=2.4.9&pid=8045&registry=zookeeper&timestamp=1491546077803

-> ServiceConfig doExportUrlsFor1Protocol()
#需要暴露 dubbo://10.199.66.242:20880/com.unj.dubbotest.provider.DemoService?anyhost=true&application=dubbo_demo_provider&dubbo=2.4.9&interface=com.unj.dubbotest.provider.DemoService&methods=sayHello,getUsers&pid=8045&revision=0.0.1&side=provider&timestamp=1491546674441&version=0.0.1

-> ServiceConfig exportLocal()
-> Exporter<?> exporter = protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
#暴露Invoker<XxxService>調用服務代理類

-> proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
#返回 AbstractProxyInvoker代理ProxyInvoker<XxxService>
public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
private final T proxy; //代理目標實例 XxxServiceImpl
private final Class<T> type;
private final URL url;
}
-> InvokerInvocationHandler.invoke()
#invoker.invoke(new RpcInvocation(method, args)).recreate();

-> DubboProtocol export(Invoker<T> invoker)
# 返回暴露Exporter<T>
public class DubboExporter<T> extends AbstractExporter<T> {
private final String key; //com.unj.dubbotest.provider.DemoService:0.0.1:20880
private final Map<String, Exporter<?>> exporterMap;
public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap){
super(invoker);
this.key = key;
this.exporterMap = exporterMap;
}

-> DubboProtocol openServer(url)
#url dubbo://10.199.66.242:20880/com.unj.dubbotest.provider.DemoService?anyhost=true&application=dubbo_demo&dubbo=2.4.9&interface=com.unj.dubbotest.provider.DemoService&methods=sayHello,getUsers&pid=8045&revision=0.0.1&side=provider&timestamp=1491546674441&version=0.0.
#serverMap.put(key, createServer(url)); key:10.199.66.242:20880 value:ExchangeServer

-> DubboProtocol createServer(URL url)
#返回HeaderExchangeServer,添加參數列表 如心跳,心跳時間
-> Exchangers.bind(url, requestHandler);
#返回HeaderExchangeServer,getTransporter()獲取的實例來源於配置,默認返回一個NettyTransporter
-> HeaderExchangeServer.bind(URL url, ExchangeHandler handler);
-> HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
#HeaderExchangeServer包裝實例NettyServer

-> NettyTransporter.bind(URL url, ChannelHandler listener)
#return new NettyServer(url, listener)

-> NettyServer.doOpen();
#打開socket監聽端口準備接收消息
#ServerBootstrap bind(getBindAddress())綁定地址端口
#RpcInvocation 具體類名、方法名、調用參數
#DubboInvoker – 執行具體的遠程調用,包含初始化信息如client
#Protocol – 服務地址的發佈和訂閱
#Exporter – 暴露服務的引用,或取消暴露

二:consume(消費方):
->ReferenceConfig.init
#consume端啓動初始化
->DubboProtocol.refer
#根據參數url,接口等構建Invoker
->JavassistProxyFactory.getProxy(Invoker<T> invoker, Class<?>[] interfaces)
#構建代理對象Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
->DemoService.say(String hello);#真正調用時候
->InvokerInvocationHandler.invoke(Object proxy, Method method, Object[] args)
#invoker.invoke(new RpcInvocation(method, args)).recreate();RpcInvocation包裝參數方法名
->DubboInvoker.doInovke(final Invocation invocation)
#統一代理調用
->ExchangeClient.send(invocation, isSent);
->HeaderExchangeChannel.request(Object request, int timeout)
->NettyChannel.send(Object message, boolean sent)

三:dubbo 底層通訊:NettyClient <-- 異步NIO傳輸 socket監聽-> NettyServer
四:consume --> provider 調用過程:
-> NettyServer->NettyHandler.messageReceived #接收消息處理器
-> MultiMessageHandler->HeartbeatHandler->AllChannelHandler->DecodeHandler->HeaderExchangeHandler->DubboProtocol$requestHandler
#NettyServer啓動時候綁定MultiMessageHandler
#DubboProtocol.getServers() 檢索serverMap獲取Exporter<?>
#DubboProtocol.getServers() 檢索serverMap獲取ExchangeServer
-> ExchangeHandlerAdapter.reply
#真正獲取Invoker,將傳入message 轉換 invocation
-> invoker.invoke(invocation)
-> JavassistProxyFactory$AbstractProxyInvoker.doInvoke
#服務端Invoker代理 AbstractProxyInvoker調用目標引用service,客戶端DubboInvoker

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章