赞
踩
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); } } }
IdleHandler继承了ChannelInboundHandlerAdapter, 载了userEventTriggered方法, 执行了关闭连接的逻辑
这个类是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); } }
创建时间间隔为readerIdleTime的定时任务。触发了一个Task, ReaderIdleTimeoutTask。
用当前时间减去最后一次channelRead方法调用的时间, 假如这个结果是6s, 说明最后一次调用channelRead已经是6s之前的事情了, 设置为5s, 那么nextDelay为-1, 说明超时了。执行③处代码, 触发channelIdle(), 执行fireUserEventTriggered(), 下一个处理器的userEventTriggered()
自定义的userEventTriggered方法, 在自带的IdleStateHandler处理器, 在心跳检测超时时, 最终会执行下一个handler的userEventTriggered方法来处理。
IdleStateHandler这个类会根据你设置的超时参数的类型和值, 循环去检测channelRead和write方法多久没有被调用了, 如果时间超过设置的时间的话, 触发对应的事件, channelRead, channelActive, channelIdle方法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。