简述Netty心跳机制

224 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 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);
    }
}

PS:

【Netty】高阶使用:IdleStateHandler 心跳检测,实现超时断开连接