在一个框架中我们通常把负责数据交换和网络通信的组件叫做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
|
public
void
send
(
Object
message
,
boolean
sent
)
throws
RemotingException
{
super
.
send
(
message
,
sent
)
;
boolean
success
=
true
;
int
timeout
=
0
;
try
{
ChannelFuture
future
=
channel
.
write
(
message
)
;
if
(
sent
)
{
timeout
=
getUrl
(
)
.
getPositiveParameter
(
Constants
.
TIMEOUT_KEY
,
Constants
.
DEFAULT_TIMEOUT
)
;
success
=
future
.
await
(
timeout
)
;
}
Throwable
cause
=
future
.
getCause
(
)
;
if
(
cause
!=
null
)
{
throw
cause
;
}
}
catch
(
Throwable
e
)
{
throw
new
RemotingException
(
this
,
"Failed to send message "
+
message
+
" to "
+
getRemoteAddress
(
)
+
", cause: "
+
e
.
getMessage
(
)
,
e
)
;
}
}
|
执行Netty的channel.write()将数据真正发送出去,也可以由此看出boolean sent;参数的含义:是否去等待发送完成、是否执行超时的判断。
本文主要以Client的角度对通信流程进行了介绍,Server端也可以遵循这样的路径去梳理,这里就不再赘述了。