dubbo请求调用过程分析
服務消費方發(fā)起請求
?
當服務的消費方引用了某遠程服務,服務的應用方在spring的配置實例如下:
?
<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService"?/>
?
demoService實例其實是代理工廠生產(chǎn)的代理對象(大家可以參考代理那部分生成的偽代碼),在代碼中調(diào)用demoService.sayHello(“world!”)時,
?
1.????? 將方法名方法參數(shù)傳入InvokerInvocationHandler的invoke方
?
對于Object中的方法toString, hashCode, equals直接調(diào)用invoker的對應方法,
?
這里對于Object的方法需要被遠程調(diào)用嗎?調(diào)用了是不是報錯比默認處理更好呢??
?
遠程調(diào)用層是以Invocation, Result為中心, 這里根據(jù)要調(diào)用的方法以及傳入的參數(shù)構建RpcInvocation對象,作為Invoker的入?yún)?/span>
?
2.????? MockClusterInvoker根據(jù)參數(shù)提供了三種調(diào)用策略
?
不需要mock, 直接調(diào)用FailoverClusterInvoker
?
強制mock,調(diào)用mock
?
先調(diào)FailoverClusterInvoker,調(diào)用失敗在mock、
?
3.????? FailoverClusterInvoker默認調(diào)用策略
?
通過目錄服務查找到所有訂閱的服務提供者的Invoker對象
?
路由服務根據(jù)策略來過濾選擇調(diào)用的Invokers
?
通過負載均衡策略LoadBalance來選擇一個Invoker
?
4.????? 執(zhí)行選擇的Invoker.inoker(invocation)
?
經(jīng)過監(jiān)聽器鏈,默認沒有
?
經(jīng)過過濾器鏈,內(nèi)置實現(xiàn)了很多
?
執(zhí)行到遠程調(diào)用的DubboInvoker
?
5.????? DubboInvoker
?
根據(jù)url 也就是根據(jù)服務提供者的長連接,這里封裝成交互層對象ExchangeClient供這里調(diào)用
?
判斷遠程調(diào)用類型同步,異步還是oneway模式
?
ExchangeClient發(fā)起遠程調(diào)用,底層remoting不在這里描述了
?
獲取調(diào)用結果:
?
??????? Oneway返回空RpcResult
?
??????? 異步,直接返回空RpcResult, ResponseFuture回調(diào)
?
??????? 同步, ResponseFuture模式同步轉異步,等待響應返回
?
?
?
?
?
服務提供方接收調(diào)用請求
?
同樣我們也是rpc調(diào)用層DubboProtocol層開始分析,對于通信層remoting的數(shù)據(jù)接收反序列等等過程不做分析。
?
DubboProtocol的requestHandler是ExchangeHandler的實現(xiàn),是remoting層接收數(shù)據(jù)后的回調(diào)。
?
requestHandler.replay方法接收請求消息,這里只處理遠程調(diào)用消息Invocation。
?
1.????? 通過Invocation獲取服務名和端口組成serviceKey=com.alibaba.dubbo.demo.DemoService:20880, 從DubboProtocol的exproterMap中獲取暴露服務的DubboExporter, 在從dubboExporter 獲取invoker返回
?
2.????? 經(jīng)過過濾器鏈
?
3.????? 經(jīng)過監(jiān)聽器鏈
?
4.????? 到達執(zhí)行真正調(diào)用的invoker, 這個invoker由代理工廠ProxyFactory.getInvoker(demoService, DemoService.class, registryUrl)創(chuàng)建,具體請看代理那部分介紹。
?
調(diào)用demoService實例方法,將結果封裝成RpcResult返回
?
5.????? 交換層構建Response,通過Remoting層編碼傳輸將結果響應給調(diào)用方
?
?
?
?
?
服務消費方發(fā)起遠程調(diào)用的底層通信
?
?
服務提供方接收請求并響應的底層通信
?
一: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®istry=zookeeper×tamp=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×tamp=1491546674441&version=0.0.1?
??
-> ServiceConfig exportLocal()?
-> Exporter<?> exporter = protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local));?
#暴露Invoker<XxxService>調(diào)用服務代理類?
??
-> 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×tamp=1491546674441&version=0.0.?
#serverMap.put(key, createServer(url)); key:10.199.66.242:20880 value:ExchangeServer?
??
-> DubboProtocol createServer(URL url)?
#返回HeaderExchangeServer,添加參數(shù)列表 如心跳,心跳時間?
-> 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監(jiān)聽端口準備接收消息?
#ServerBootstrap bind(getBindAddress())綁定地址端口?
#RpcInvocation 具體類名、方法名、調(diào)用參數(shù)?
#DubboInvoker – 執(zhí)行具體的遠程調(diào)用,包含初始化信息如client?
#Protocol – 服務地址的發(fā)布和訂閱?
#Exporter – 暴露服務的引用,或取消暴露?
??
二:consume(消費方):?
->ReferenceConfig.init?
#consume端啟動初始化?
->DubboProtocol.refer?
#根據(jù)參數(shù)url,接口等構建Invoker?
->JavassistProxyFactory.getProxy(Invoker<T> invoker, Class<?>[] interfaces)?
#構建代理對象Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));?
??
->DemoService.say(String hello);#真正調(diào)用時候?
->InvokerInvocationHandler.invoke(Object proxy, Method method, Object[] args)?
#invoker.invoke(new RpcInvocation(method, args)).recreate();RpcInvocation包裝參數(shù)方法名?
->DubboInvoker.doInovke(final Invocation invocation)?
#統(tǒng)一代理調(diào)用?
->ExchangeClient.send(invocation, isSent);?
->HeaderExchangeChannel.request(Object request, int timeout)?
->NettyChannel.send(Object message, boolean sent)?
??
三:dubbo 底層通訊:NettyClient <-- 異步NIO傳輸 socket監(jiān)聽-> NettyServer?
??
四:consume --> provider 調(diào)用過程:?
-> 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調(diào)用目標引用service原文鏈接:[http://wely.iteye.com/blog/2378164]
總結
以上是生活随笔為你收集整理的dubbo请求调用过程分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据人力资源服务平台正式上线
- 下一篇: 专门针对科学家工程师的僵尸网络