1.概述
exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer。
类图:
2.ExchangeChannel
继承 Channel 接口,信息交换通道接口。方法如下:
/**
* ExchangeChannel. (API/SPI, Prototype, ThreadSafe)
*
* 信息交换通道接口
*/
public interface ExchangeChannel extends Channel {
/**
* send request.
*
* 发送请求
*
* @param request 请求
* @return response future
* @throws RemotingException 远程调用,发生异常
*/
ResponseFuture request(Object request) throws RemotingException;
/**
* send request.
*
* 发送请求
*
* @param request 请求
* @param timeout 超时时长
* @return response future
* @throws RemotingException 远程调用,发生异常
*/
ResponseFuture request(Object request, int timeout) throws RemotingException;
/**
* get message handler.
*
* 获得信息交换处理器
*
* @return message handler
*/
ExchangeHandler getExchangeHandler();
/**
* graceful close.
*
* 优雅关闭
*
* @param timeout 超时时长
*/
void close(int timeout);
}
2.1 HeaderExchangeChannel
现 ExchangeChannel 接口,基于消息头部( Header )的信息交换通道实现类。
构造方法:
/**
* ExchangeReceiver
*
* 基于消息头部( Header )的信息交换通道实现类
*/
final class HeaderExchangeChannel implements ExchangeChannel {
private static final Logger logger = LoggerFactory.getLogger(HeaderExchangeChannel.class);
/**
* 通道键
*/
private static final String CHANNEL_KEY = HeaderExchangeChannel.class.getName() + ".CHANNEL";
/**
* 通道
*/
private final Channel channel;
/**
* 是否关闭
*/
private volatile boolean closed = false;
HeaderExchangeChannel(Channel channel) {
if (channel == null) {
throw new IllegalArgumentException("channel == null");
}
this.channel = channel;
}
}
getOrAddChannel(Channel) 静态方法,创建 HeaderExchangeChannel 对象。代码如下:
/**
* 创建 HeaderExchangeChannel 对象
*
* @param ch 通道
* @return HeaderExchangeChannel 对象
*/
static HeaderExchangeChannel getOrAddChannel(Channel ch) {
if (ch == null) {
return null;
}
HeaderExchangeChannel ret = (HeaderExchangeChannel) ch.getAttribute(CHANNEL_KEY);
if (ret == null) {
ret = new HeaderExchangeChannel(ch);
if (ch.isConnected()) { // 已连接
ch.setAttribute(CHANNEL_KEY, ret);
}
}
return ret;
}
发送请求:
@Override
public ResponseFuture request(Object request, int timeout) throws RemotingException {
if (closed) {
throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!");
}
// create request. 创建请求
Request req = new Request();
req.setVersion("2.0.0");
req.setTwoWay(true); // 需要响应
req.setData(request);
// 创建 DefaultFuture 对象
DefaultFuture future = new DefaultFuture(channel, req, timeout);
try {
// 发送请求
channel.send(req);
} catch (RemotingException e) { // 发生异常,取消 DefaultFuture
future.cancel();
throw e;
}
// 返回 DefaultFuture 对象
return future;
}
优雅关闭:
@Override
public void close(int timeout) {
if (closed) {
return;
}
closed = true;
// 等待请求完成
if (timeout > 0) {
long start = System.currentTimeMillis();
while (DefaultFuture.hasFuture(channel) && System.currentTimeMillis() - start < timeout) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
logger.warn(e.getMessage(), e);
}
}
}
// 关闭通道
close();
}
3. ExchangeClient
Client ,ExchangeChannel 接口,信息交换客户端接口。
无自定义方法。