介绍
先来看下Dubbo
的整体架构图。Exchange
在倒数第三层。我用黄色线框框出来的区域。
Exchange
层,属于信息交换层,是对Request
和Response
的抽象。
为什么要单独抽象出一个Exchange
层,而不是在Protocol
层直接对Netty
或者Mina
引用?这个问题其实不难理解,Netty
或者Mina
对外接口和调用方式都不一样,如果在Protocol
层直接对Mina
做引用,对于Protocol
层来讲,就依赖了具体而不是抽象,过几天想要换成Netty
,就需要对Protocol
层做大量的修改。这样不符合开闭原则。
Dubbo
使用的是TCP
长连接,与我们开发常见到的HTTP
协议(HTTP
本身与TCP
也不在同一层)不同 。TCP
本身没有Request
和Response
的概念。只有发送和接收。HTTP
协议中的Request
和Response
是由Http
服务器或者Servlet
容器来实现的。
Dubbo
要使用TCP
长连接,就得自己实现Request
和Response
的抽象概念,这样客户端与服务端之间的交互才能有去有回。
说下交互流程:A服务首先向B服务发送【TCP
消息】,B服务收到请求后,做业务处理,然后向A服务发送【TCP
消息】
看代码
先看Exchanger
接口
public interface Exchanger {
// 抽象出了bind行为,这个行为要完成服务端口暴露的动作,并且返回ExchangeServer抽象
// Protocol层只需要给URL和handler就可以完成端口暴露的动作
ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException;
// 抽象出了connect行为,这个行为要完成客户端与服务端的连接动作,并且返回ExchangeClient抽象
// Protocol层只需要给URL和handler就可以完成端口暴露的动作
ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException;
}
Exchanger
只有一个实现HeaderExchanger
public class HeaderExchanger implements Exchanger {
public static final String NAME = "header";
@Override
public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
// 与服务端建立TCP连接,并且返回HeaderExchangeClient
// Request和Response的概念提现要详细关注HeaderExchangeHandler
return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);
}
@Override
public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
// 暴露服务,并且返回HeaderExchangeServer
// Request和Response的概念提现要详细关注HeaderExchangeHandler
return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
}
}
public class HeaderExchangeHandler implements ChannelHandlerDelegate {
// ----------------------此处生路一堆代码------------------------
@Override // 接受信息
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
if (message instanceof Request) {
// 看看信息是不是Request
// handle request.
Request request = (Request) message;
if (request.isEvent()) {
handlerEvent