Netty心跳检测机制实现
思路实现详见注释代码
//心跳检测机制:
/**
* 使用背景,客户端实际端口,然后任然暂用tcp连接导致服务器压力大,采取的
* 适当实际的检测机制
*
* 实现思路:间隔一段实际发送一段(心跳检测包)
*/
//间隔时间触发一个事件(告诉服务器进行检测)
/**
* 会不压力很大:每一轮心跳会如果gc一样,耗时,有stw
* 不会:
* channel为每个连接的管道。这里的处理器为实际的‘工序’
* 因此这里抛出的一个事件仅仅是作用于这一个管道,并不会使得全局爆发
* 而是对于每一个channel平均分摊效果
*/
socketChannel.pipeline().addLast(new IdleStateHandler(
5,
0,
0));
/**
* 这个类便是监听上事件抛出的处理方法,
* 针对于用户事件
* ,在内部实现可以拿到具体是什么方法触发
*/
socketChannel.pipeline().addLast(new ChannelDuplexHandler(){
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
if ( idleStateEvent.state() == IdleState.READER_IDLE ){
log.debug("已经5s没有发送事件了");
}
super.userEventTriggered(ctx, evt);
}
});
当然,仅仅是服务器开启这种定时检测机制是有很多弊端的:
如果客户端真正输入,而不是断开了连接等等的情况,实际上,是不因该断开连接的。那么应该怎么办呢:
客户端自身维护轮询机制,在一段时间后给服务器发送消息。
贴代码
ch.pipeline().addLast(new IdleStateHandler(
0,
3,
0));
ch.pipeline().addLast(new ChannelDuplexHandler(){
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
if (idleStateEvent.state() == IdleState.WRITER_IDLE){
//建议发送更为专门的消息
ch.writeAndFlush(new ChatRequestMessage());
}
}
});
这样就互相直接实现了一种心跳检测机制,可以保证连接的时效性,正确性。