有时候因为网络设置为飞行模式服务器接收不到客户端断开连接标志,或者我们长时间没有操作,这些可能都会造成服务器资源的占用。我们需要让Netty能够定期检测某个通道是否空闲,如果空闲超过一定的时间,就可以将对应客户端的通道资源关闭。
纯后端检测机制
类似于设置一定时间Netty服务器没有活动了,没接收消息,没写数据,就向客户端发送一次事件消息,看看客户端是否还存活
想要实现这个很简单
1.修改通道初始化器
//添加netty空闲超时检查机制
//1.读空闲 (一定时间没有从服务器啦数据)(超过一定时间就发送对应的事件消息)
//2/写空闲超时(一定时间没有向Netty服务器写数据)
//3.读写空闲
//第一个参数设置未读时间,第二个参数设置为未写时间,第三个为都未进行操作的时间
//单位秒
channelPipeline.addLast(new IdleStateHandler(4,8,12));
//添加超时检查机制--事件消息捕获类
channelPipeline.addLast(new HeatBeatHandler());
2.添加事件检测捕获类
ChannelInboundHandlerAdapter里的userEventTriggered方法可以监听Netty服务器的所有事件
我们这里判断如果监听到的事件属于我们定义的IdleStateEvent超时状态事件,那么我们就对其做一定处理
我这里做的处理是如果超过一定事件没有进行读和写,直接关闭通道.
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
public class HeatBeatHandler extends ChannelInboundHandlerAdapter {
@Override//用户事件触发
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent){//如果接收到的事件消息属于我们之前定义的心跳事件
IdleStateEvent idleStateEvent=(IdleStateEvent) evt;//将该事件消息强转为心跳事件
//这里虽然监听了三种空闲,但是我们只对读写空闲做操作
if(idleStateEvent.state()== IdleState.READER_IDLE){ //如果是读空闲
System.out.println("读空闲事件触发...");
}else if (idleStateEvent.state()== IdleState.WRITER_IDLE){
System.out.println("写空闲事件触发...");
}else if (idleStateEvent.state()== IdleState.ALL_IDLE){
System.out.println("===============================================");
System.out.println("读写空闲事件触发...");
System.out.println("关闭该通道资源");
ctx.channel().close();//关闭该通道
}
}
}
}
12秒后的读写超时事件触发关闭通道

网友评论