Netty心跳检测之IdleStateHandler

服务端Selector监听到NioSochetChannel的连接事件后,需要通过boss线程启动一个worker线程驱动的事件循环组,并且将当前NioSochetChannel注册至worker线程的Selector上并且监听相关NioSochetChannel存在的IO事件。

在服务端NioSochetChannel在worker线程的Selector上注册register0过程中,会为当前的NioSochetChannel填充自定义的ChannelHandler时涉及相关心跳的ChannelHandler之IdleStateHandler

IdleStateHandler提供了三种类型的IdleStateEvent:read, write, or both operation for a while。每种类型的定时事件都对应一个AbstractIdleTask类型的定时任务ReaderIdleTimeoutTaskWriterIdleTimeoutTaskAllIdleTimeoutTask

public class IdleStateHandler extends ChannelDuplexHandler {

		public IdleStateHandler(boolean observeOutput,long readerIdleTime, 
																long writerIdleTime, long allIdleTime,TimeUnit unit) {
        readerIdleTimeNanos = Math.max(unit.toNanos(readerIdleTime), MIN_TIMEOUT_NANOS);
        writerIdleTimeNanos = Math.max(unit.toNanos(writerIdleTime), MIN_TIMEOUT_NANOS);
        allIdleTimeNanos = Math.max(unit.toNanos(allIdleTime), MIN_TIMEOUT_NANOS);
    }
	
		private void initialize(ChannelHandlerContext ctx) {
        ...
        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);
        }
    }
}
public abstract class AbstractScheduledEventExecutor{

		PriorityQueue<ScheduledFutureTask<?>> scheduledTaskQueue;
		
		@Override
		public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
			...
			return schedule(new ScheduledFutureTask<Void>(this,command,
		        	deadlineNanos(getCurrentTimeNanos(), unit.toNanos(delay))));
		}
		
		public static long deadlineNanos(long nanoTime, long delay) {
			//当前时间 + 延迟纳秒数
         	long deadlineNanos = nanoTime + delay;
         	return deadlineNanos < 0 ? Long.MAX_VALUE : deadlineNanos;
    	}
		
		private <V> ScheduledFuture<V> schedule(final ScheduledFutureTask<V> task) {
		    if (inEventLoop()) {
		        scheduledTaskQueue.add(task.setId(++nextTaskId));
		    } else {
		        ...
		    }
		    return task;
		}
}

最后将三种类型的任务task均抽象为ScheduledFutureTask类型的任务,并添加至优先队列scheduledTaskQueue中。

1.AbstractIdleTask任务初始化时机

IdleStateHandler 被添加至 NioSochetChannel对应的pipeline过程中。意味着服务端监听到每个客户端NioSochetChannel连接事件后,会为每个NioSochetChannel的pipeline中添加一个IdleStateHandler类型的channelHandler。

public class DefaultChannelPipeline implements ChannelPipeline {
		public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
		    AbstractChannelHandlerContext newCtx;
		    synchronized (this) {
		        newCtx = newContext(group, filterName(name, handler), handler);
		        addLast0(newCtx);
					  ...
		    }
		    callHandlerAdded0(newCtx);//真正调用IdleStateHandler的initialize方法
		    return this;
		}
}

2.优先队列PriorityQueue添加至普通队列

优先队列PriorityQueue中元素类型为ScheduledFutureTask:

  1. 将 PriorityQueue中元素ScheduledFutureTask 添加至循环事件组监听的普通队列中。
  2. 由 worker线程负责触发 ScheduledFutureTask类型的任务。
public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor{
		private final Queue<Runnable> taskQueue;
		protected boolean runAllTasks(long timeoutNanos) {
		    fetchFromScheduledTaskQueue();
		    Runnable task = pollTask();
		    ...
		    final long deadline = timeoutNanos > 0 ? getCurrentTimeNanos() + timeoutNanos : 0;
		    long runTasks = 0;
		    long lastExecutionTime;
		    for (;;) {//worker线程循环处理taskQueue中全部任务
		        safeExecute(task);
		        runTasks ++;
		        ...
		    }
		    return true;
		}
		
		private boolean fetchFromScheduledTaskQueue() {
        if (scheduledTaskQueue == null || scheduledTaskQueue.isEmpty()) {
            return true;
        }
        long nanoTime = getCurrentTimeNanos();
        for (;;) {//循环将PriorityQueue队列中ScheduledFutureTask类型任务添加至taskQueue终
            Runnable scheduledTask = pollScheduledTask(nanoTime);
            if (scheduledTask == null) {
                return true;
            }
            if (!taskQueue.offer(scheduledTask)) {
                scheduledTaskQueue.add((ScheduledFutureTask<?>) scheduledTask);
                return false;
            }
        }
    }
}

3.ScheduledFutureTask

ScheduledFutureTask任务是被当做普通队列中任务后被worker线程触发执行。

final class ScheduledFutureTask<V> extends PromiseTask<V> implements ScheduledFuture<V>, PriorityQueueNode {
    // AbstractIdleTask类型的任务触发的截止时间
    private long deadlineNanos;
    /* 0 - no repeat, >0 - repeat at fixed rate, <0 - repeat with fixed delay */
    private final long periodNanos;//默认值0

    @Override
    public void run() {
        //当前时间与AbstractIdleTask截止时间比较,是否过期
        if (delayNanos() > 0L) {// 条件成立,意味着 AbstractIdleTask 任务执行时已经超过截止时间了
            if (isCancelled()) {
                scheduledExecutor().scheduledTaskQueue().removeTyped(this);
            } else {
                scheduledExecutor().scheduleFromEventLoop(this);
            }
            return;
        }
        if (periodNanos == 0) {
            if (setUncancellableInternal()) {
                V result = runTask();// 直接触发AbstractIdleTask任务的执行
                setSuccessInternal(result);
            }
        } else {
            // check if is done as it may was cancelled
            if (!isCancelled()) {
                runTask();
                ...
            }
        }
    }
}

4.AbstractIdleTask

以 AllIdleTimeoutTask 类型为例。

public class IdleStateHandler extends ChannelDuplexHandler {
		// channelRead设置为true,channelReadComplete设置为false
		private boolean reading;// 默认值为false
		private long lastReadTime;
		private long lastWriteTime;

    private final class AllIdleTimeoutTask extends AbstractIdleTask {
			 	
        @Override
        protected void run(ChannelHandlerContext ctx) {
            long nextDelay = allIdleTimeNanos;
            if (!reading) {
            		// channelReadComplete 设置 lastReadTime 为当前时间
                nextDelay -= ticksInNanos() - Math.max(lastReadTime, lastWriteTime);
            }
            if (nextDelay <= 0) {// 说明已经达到定时任务触发时间
                allIdleTimeout = schedule(ctx, this, allIdleTimeNanos, TimeUnit.NANOSECONDS);
                boolean first = firstAllIdleEvent;
                firstAllIdleEvent = false;
                if (hasOutputChanged(ctx, first)) {
                    return;
                }
                IdleStateEvent event = newIdleStateEvent(IdleState.ALL_IDLE, first);
                channelIdle(ctx, event);//触发入栈ChannelHandler#fireUserEventTriggered
            } else {
                allIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值