seata 客户端如何接收响应消息
seata是使用CompletableFuture来处理响应结果的。seata单独封装了MessageFuture类,用来包裹CompletableFuture:
public class MessageFuture {
private RpcMessage requestMessage;
private long timeout;
private long start = System.currentTimeMillis();
private transient CompletableFuture<Object> origin = new CompletableFuture<>();
}
在AbstractNettyRemoting抽象类中,seata定义了一个futures变量,用来存放MessageFuture信息:
protected final ConcurrentHashMap<Integer, MessageFuture> futures = new ConcurrentHashMap<>();
在AbstractNettyRemoting抽象类中,发送消息方法sendSyn会将创建MessageFuture实例,并将MessageFuture实例缓存futures中。
MessageFuture messageFuture = new MessageFuture();
messageFuture.setRequestMessage(rpcMessage);
messageFuture.setTimeout(timeoutMillis);
futures.put(rpcMessage.getId(), messageFuture);
channelWritableCheck(channel, rpcMessage.getBody());
String remoteAddr = ChannelUtil.getAddressFromChannel(channel);
doBeforeRpcHooks(remoteAddr, rpcMessage);
// 发送消息
channel.writeAndFlush(rpcMessage).addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
MessageFuture messageFuture1 = futures.remove(rpcMessage.getId());
if (messageFuture1 != null) {
messageFuture1.setResultMessage(future.cause());
}
destroyChannel(future.channel());
}
});
try {
// 获取响应结果,如果获取不到会一直等待,直到超时
Object result = messageFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);
doAfterRpcHooks(remoteAddr, rpcMessage, result);
return result;
} catch (Exception exx) {
LOGGER.error("wait response error:{},ip:{},request:{}", exx.getMessage(), channel.remoteAddress(), rpcMessage.getBody());
if (exx instanceof TimeoutException) {
throw (TimeoutException) exx;
} else {
throw new RuntimeException(exx);
}
}
客户端在注册Processor时,会通过ClientOnResponseProcessor类,获取futures.
ClientOnResponseProcessor onResponseProcessor = new ClientOnResponseProcessor(mergeMsgMap, super.getFutures(), getTransactionMessageHandler());
这样,客户端在接收到服务端的消息时,会将响应结果set进MessageFuture中:
MessageFuture messageFuture = futures.remove(rpcMessage.getId());
if (messageFuture != null) {
// 设置响应结果,此时messageFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);获取结果等待结束
messageFuture.setResultMessage(rpcMessage.getBody());
} else {
if (rpcMessage.getBody() instanceof AbstractResultMessage) {
if (transactionMessageHandler != null) {
transactionMessageHandler.onResponse((AbstractResultMessage) rpcMessage.getBody(), null);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?