> 文章列表 > [Netty] Netty自带的心跳机制 (十五)

[Netty] Netty自带的心跳机制 (十五)

[Netty] Netty自带的心跳机制 (十五)

文章目录

      • 1.IdleStateHandler介绍
      • 2.IdleStateHandler源码解析
      • 3.IdleStateHandler总结

1.IdleStateHandler介绍

Netty服务端心跳机制: IdleStateHandler, 这个类可以对三种类型的心跳检测。

@ChannelHandler.Sharable
public class IdleHandler extends ChannelInboundHandlerAdapter {private static final Logger LOG = LoggerFactory.getLogger(IdleHandler.class);@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object paramObject) throws Exception {LOG.info("userEventTriggered");if (paramObject instanceof IdleStateEvent) {IdleState state = ((IdleStateEvent) paramObject).state();if (state == IdleState.ALL_IDLE) {//关闭连接ctx.channel().close();}} else {super.userEventTriggered(ctx, paramObject);}}
}

IdleHandler继承了ChannelInboundHandlerAdapter, 载了userEventTriggered方法, 执行了关闭连接的逻辑

[Netty] Netty自带的心跳机制 (十五)

2.IdleStateHandler源码解析

[Netty] Netty自带的心跳机制 (十五)

  • readerIdleTime:为读超时时间(即测试端一定时间内未接受到被测试端消息
  • writerIdleTime:为写超时时间(即测试端一定时间内向被测试端发送消息)
  • allIdleTime:所有类型的超时时间

[Netty] Netty自带的心跳机制 (十五)

这个类是ChannelHandler, 会被加载如ChannelPipeline。

[Netty] Netty自带的心跳机制 (十五)

让channelPipe中的下一个handler处理channelRead方法。

fireChannelRead用法: fireChannelRead表示传递消息至下一个处理器, 因为Pipeline的原因, 有 一个链式的处理队列, 消息为队列的头处理器进入。

比如如果A, B, C处理器, 如果A处理器没有fireChannelRead方法, 那么B, C不会接受到消息。

[Netty] Netty自带的心跳机制 (十五)

IdleStateHandler的精髓。

    private void initialize(ChannelHandlerContext ctx) {// Avoid the case where destroy() is called before scheduling timeouts.// See: https://github.com/netty/netty/issues/143switch (state) {case 1:case 2:return;}state = 1;initOutputChanged(ctx);lastReadTime = lastWriteTime = ticksInNanos();if (readerIdleTimeNanos > 0) {readerIdleTimeout = schedule(ctx, new ReaderIdleTimeoutTask(ctx),readerIdleTimeNanos, TimeUnit.NANOSECONDS);}if (writerIdleTimeNanos > 0) {writerIdleTimeout = schedule(ctx, new WriterIdleTimeoutTask(ctx),writerIdleTimeNanos, TimeUnit.NANOSECONDS);}if (allIdleTimeNanos > 0) {allIdleTimeout = schedule(ctx, new AllIdleTimeoutTask(ctx),allIdleTimeNanos, TimeUnit.NANOSECONDS);}}

创建时间间隔为readerIdleTime的定时任务。触发了一个Task, ReaderIdleTimeoutTask。

[Netty] Netty自带的心跳机制 (十五)

[Netty] Netty自带的心跳机制 (十五)

用当前时间减去最后一次channelRead方法调用的时间, 假如这个结果是6s, 说明最后一次调用channelRead已经是6s之前的事情了, 设置为5s, 那么nextDelay为-1, 说明超时了。执行③处代码, 触发channelIdle(), 执行fireUserEventTriggered(), 下一个处理器的userEventTriggered()

[Netty] Netty自带的心跳机制 (十五)

自定义的userEventTriggered方法, 在自带的IdleStateHandler处理器, 在心跳检测超时时, 最终会执行下一个handler的userEventTriggered方法来处理。

3.IdleStateHandler总结

IdleStateHandler这个类会根据你设置的超时参数的类型和值, 循环去检测channelRead和write方法多久没有被调用了, 如果时间超过设置的时间的话, 触发对应的事件, channelRead, channelActive, channelIdle方法

  1. 如果超时了, 则会调用userEventTriggered方法, 且会告诉你超时的类型
  2. 如果没有超时, 则会循环定时检测, 除非你将IdleStateHandler移除Pipeline