當服務的消費方引用了某遠程服務,服務的應用方在spring的配置實例以下:java
<dubbo:referenceid="demoService"interface="com.alibaba.dubbo.demo.DemoServ ice" />spring
demoService實例實際上是代理工廠生產的代理對象(你們能夠參考代理那部分生成的僞代碼),在代碼中調用demoService.sayHello(「world!」)時,app
1. 將方法名方法參數傳入InvokerInvocationHandler的invoke方負載均衡
對於Object中的方法toString, hashCode, equals直接調用invoker的對應方法,異步
這裏對於Object的方法須要被遠程調用嗎?調用了是否是報錯比默認處理更好呢??socket
遠程調用層是以Invocation, Result爲中心, 這裏根據要調用的方法以及傳入的參數構建RpcInvocation對象,做爲Invoker的入參ide
2. MockClusterInvoker根據參數提供了三種調用策略this
不須要mock, 直接調用FailoverClusterInvoker編碼
強制mock,調用mockurl
先調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®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>調用服務代理類
-> 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,添加參數列表 如心跳,心跳時間
-> 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