在一个框架中我们通常把负责数据交换和网络通信的组件叫做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端也可以遵循这样的路径去梳理,这里就不再赘述了。