fix(netty): 优化异常处理和心跳超时逻辑

- 改进异常捕获日志格式,添加channel哈希值标识
- 修正异常处理逻辑,确保合法连接断开时调用离线服务
- 优化心跳超时处理,统一连接关闭逻辑
- 添加详细的注释说明异常处理和超时断连策略
This commit is contained in:
2026-04-10 10:34:45 +08:00
parent dc14a57686
commit cf72d1c704

View File

@@ -127,15 +127,15 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
*/ */
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
logger.error("ServerHandler exceptionCaught",cause);
Channel channel = ctx.channel(); Channel channel = ctx.channel();
ChannelParam param = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get(); logger.error("{} - ServerHandler exceptionCaught",channel.hashCode(),cause);
// Integer venueId = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getVenueId(); if(channel.isActive()) {
// String deviceName = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceName(); ChannelParam param = channel.attr(NettyConstant.CHANNEL_PARAM).get();
// DeviceType deviceType = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceType(); // 无论是合法连接还是非法扫描发来的乱码,发生错误立马掐断连接,绝不能手软
// messageService.Offline(deviceName,venueId,deviceType);
if(channel.isActive() && param != null && param.getVenueId() != null) { if(channel.isActive() && param != null && param.getVenueId() != null) {
// 错误产生,关闭连接 messageService.Offline(param.getDeviceName(),param.getVenueId());
logger.info("{} - {} ServerHandler exceptionCaught{}",channel.hashCode(),param.getDeviceName(),param.getVenueId(),cause);
}
ctx.close(); ctx.close();
} }
} }
@@ -149,18 +149,21 @@ public class ServerHandler extends SimpleChannelInboundHandler<String> {
if (evt instanceof IdleStateEvent){ if (evt instanceof IdleStateEvent){
IdleState state = ((IdleStateEvent) evt).state(); IdleState state = ((IdleStateEvent) evt).state();
if (state == IdleState.READER_IDLE){ if (state == IdleState.READER_IDLE){
logger.info("IdleStateEvent READER_IDLE 超时"); logger.info("IdleStateEvent READER_IDLE 超时,主动断开连接");
ChannelParam param = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get(); Channel channel = ctx.channel();
if (param != null && param.getVenueId() != null) { ChannelParam param = channel.attr(NettyConstant.CHANNEL_PARAM).get();
// 原有逻辑 if(channel.isActive() && param != null && param.getVenueId() != null) {
Integer venueId = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getVenueId(); logger.info("{} IdleStateEvent READER_IDLE 超时,{}主动断开连接",param.getDeviceName(),param.getVenueId());
String deviceName = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getDeviceName(); }
messageService.Offline(deviceName,venueId); // 无论是否是有效设备只要读超时120秒未收到任何数据就应该关闭连接。
ctx.channel().close(); // 关闭连接会触发 channelInactive在 channelInactive 中会根据 venueId 判断是否需要处理离线逻辑。
} channel.close();
} }
} }
// 由于每次 Idle 都会打日志显得冗余,这里只在有必要时看
Set<String> connections = messageService.countConnection(); Set<String> connections = messageService.countConnection();
// 如果想要干净的日志,这个连接池统计其实可以去掉,或者缩小为 DEBUG
logger.info("count connected device ! the count is " + connections.size() + " and they are + [" + connections.toString() + "]" ); logger.info("count connected device ! the count is " + connections.size() + " and they are + [" + connections.toString() + "]" );
} }