在一個框架中我們通常把負責數據交換和網絡通信的組件叫做Exchanger。Dubbo中每個Invoker都維護了一個ExchangeClient的引用,並通過它和遠程的Server進行通信。整個與ExchangeClient相關的類圖如下
其中包含了remoting相關的接口定義。個人覺得這個接口設計有些過於發雜,但爲了可以展示全貌還是把全部內容都畫了進去。
ExchangeClient只有一個常用的實現類,HeaderExchangeClient
先通過url獲取Exchanger,默認返回一個HeaderExchanger,之後通過它的connect()創建HeaderExchangeClient。
在Invoker需要發送數據時,單程發送使用的是ExchangeClient的send方法,需要返回結果的使用request方法
在實現中這個調用被傳遞到HeaderExchangeClient維護的HeaderExchangeChannel對象,而channel後續的具體操作又依賴構造函數中傳入的Client,這個參數實際是一個Channel接口。
最終send方法傳遞到channel的send,而request方法則是通過構建ResponseFuture和調用send組合實現的。接下來的重點就是這個Channel參數如何來構建
它來自Transporters的connect方法,具體的Transporter來源於ExtensionLoader,默認爲NettyTransporter,由它構建的是NettyClient。NettyClient再次維護了一個Channel引用,來自NettyChannel的getOrAddChannel()方法,創建的是NettyChannel。最終由基類AbstractClient實現的send方法調用了NettyChannel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
publicvoidsend(Objectmessage,booleansent)throwsRemotingException{
super.send(message,sent);
booleansuccess=true;
inttimeout=0;
try{
ChannelFuturefuture=channel.write(message);
if(sent){
timeout=getUrl().getPositiveParameter(Constants.TIMEOUT_KEY,Constants.DEFAULT_TIMEOUT);
success=future.await(timeout);
}
Throwablecause=future.getCause();
if(cause!=null){
throwcause;
}
}catch(Throwablee){
thrownewRemotingException(this,"Failed
to send message "+message+"
to "+getRemoteAddress()+",
cause: "+e.getMessage(),e);
}
}
|
執行Netty的channel.write()將數據真正發送出去,也可以由此看出boolean sent;參數的含義:是否去等待發送完成、是否執行超時的判斷。
本文主要以Client的角度對通信流程進行了介紹,Server端也可以遵循這樣的路徑去梳理,這裏就不再贅述了。