“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情”
心跳机制主要是客户端和服务端长时间连接时,客户端需要定时发送心跳包来保证自己是存活的,否则一个连接长时间没有作用,浪费服务端的资源
实现:
- 在nettyClient上设定心跳检测,ChannelPipeline中写入IdleStateHandler(Netty 已经为我们提供了心跳的 Handler)
- 使用TCP的keepAlive机制,缺点是默认心跳时间2h,不够灵活
IdleStateHandler心跳检测实例
- 服务端添加自定义处理Handler类实现userEventTriggered()方法作为超时时间的处理
-
- socketChannel.pipeline().addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS)) ;
- 设定IdleStateHandler心跳检测每五秒进行一次读检测,如果五秒内ChannelRead()方法未被调用则触发一次userEventTrigger()方法
- 客户端添加IdleStateHandler心跳检测处理器,并添加自定义处理Handler类实现userEventTriggered()方法作为超时事件的逻辑处理;
public IdleStateHandler(
int readerIdleTimeSeconds,
int writerIdleTimeSeconds,
int allIdleTimeSeconds) {
this(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds,
TimeUnit.SECONDS);
}
- readerIdleTimeSeconds:读超时。即当在指定的时间间隔内没有从 Channel 读取到数据时,会触发一个 READER_IDLE 的 IdleStateEvent 事件
- writerIdleTimeSeconds: 写超时。即当在指定的时间间隔内没有数据写入到 Channel 时,会触发一个 WRITER_IDLE 的 IdleStateEvent 事件
- allIdleTimeSeconds: 读/写超时。即当在指定的时间间隔内没有读或写操作时,会触发一个 ALL_IDLE 的 IdleStateEvent 事件
心跳机制在RPC场景中就有所表现,服务端可以将IdleStateHandler组件加入到责任链中(使用Netty进行通信时), 设定IdleStateHandler心跳检测每30秒进行一次读检测,如果30秒内ChannelRead()方法未被调用则触发一次userEventTrigger()方法,服务端处理类即可重写userEventTrigger(),应对长时间未收到心跳包从而断开连接。
pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS))
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if(evt instanceof IdleStateEvent){
IdleState state = ((IdleStateEvent) evt).state();
if(state == IdleState.READER_IDLE){
logger.info("长时间未收到心跳包,断开连接……");
ctx.close();
}
}else {
super.userEventTriggered(ctx, evt);
}
}