【发布时间】:2018-02-20 11:34:36
【问题描述】:
我正在制作满足以下条件的Netty Server:
- 当服务器从客户端收到数据包时,它需要执行事务处理 A。
- 事务完成后,如果仍处于连接状态,则向客户端返回返回消息。如果没有,请执行一些回滚过程 B。
但我的问题是当我发回客户端时,服务器不知道它是否仍然连接。
在发送消息之前,我尝试了以下代码来确定其连接。但是,即使客户端已经关闭了它的套接字,它也总是会成功。只有当客户端进程被强行杀死时才会失败(例如Ctrl+C)
final ChannelFuture cf = inboundChannel.writeAndFlush(resCodec);
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
inboundChannel.close();
} else {
try {
// do Rollback Process B Here
}
}
});
我认为这是因为 TCP 协议。如果客户端正常断开连接,则向服务器发送 FIN 信号。所以它确实认为 writeAndFlush 以某种方式成功,即使它没有成功。
所以我也尝试过以下代码,但结果相同(总是返回 true)
if(inboundChannel.isActive()){
inboundChannel.writeAndFlush(msg);
} else{
// do RollBack B
}
// Similar codes using inboundChannel.isOpen(), inboundChannel.isWritable()
在我的例子中,“channelInactive”事件和“对等连接重置”异常都没有发生。
这是我使用的 Netty 测试客户端代码的一部分。
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(message).addListener(ChannelFutureListener.CLOSE);
}
如何在我想回复的时候注意到断线?
【问题讨论】:
-
这与 SMTP 协议中可能发生的问题相同,邮件服务器收到了邮件,但客户端不知道。解决此问题的方法之一是使用客户端生成的事务编号,当客户端“重新连接”时,询问有关该事务 id 的状态
-
即使您确实检测到断开连接的客户端,也不应尝试回滚。他告诉你执行交易,你执行了它:你无法向他确认,但这是问题,不是你的。解决方案是设计您的事务,使它们幂等,即重新应用已应用的事务没有任何作用。