当前位置:   article > 正文

[Netty] Netty自带的心跳机制 (十五)_idlestatehandler给服务端发心跳

idlestatehandler给服务端发心跳

1.IdleStateHandler介绍

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

@ChannelHandler.Sharable
public class IdleHandler extends ChannelInboundHandlerAdapter {
    private static final Logger LOG = LoggerFactory.getLogger(IdleHandler.class);

    @Override
    public 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);
        }


    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

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

在这里插入图片描述

2.IdleStateHandler源码解析

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

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

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

在这里插入图片描述

IdleStateHandler的精髓。

    private void initialize(ChannelHandlerContext ctx) {
        // Avoid the case where destroy() is called before scheduling timeouts.
        // See: https://github.com/netty/netty/issues/143
        switch (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);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

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

3.IdleStateHandler总结

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

  1. 如果超时了, 则会调用userEventTriggered方法, 且会告诉你超时的类型
  2. 如果没有超时, 则会循环定时检测, 除非你将IdleStateHandler移除Pipeline
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号