首页  

Netty EventLoop     所属分类 netty 浏览量 92
Netty EventLoop 用于处理I/O事件
它是一个单线程执行器,同时维护了一个Selector,用于处理Channel上的IO事件。
EventLoop继承自EventExecutor和ScheduledExecutorService,因此可以直接将任务交给EventLoop执行

每个 EventLoop 都有一个任务队列(TaskQueue),用于存放需要延迟执行或异步执行的任务。
这些任务可以是定时任务、I/O操作、用户自定义的任务等


任务队列的主要用途包括:
用户程序自定义的普通任务:这些任务通常是由用户提交的,用于处理一些非I/O相关的业务逻辑。
用户自定义定时任务:这些任务用于在指定的时间点执行某些操作,例如定时发送心跳包或定期清理资源。
非当前Reactor线程调用Channel的各种方法:在某些情况下,可能需要在非当前的Reactor线程中调用Channel的方法,这时可以通过任务队列来异步执行这些操作

网络事件、普通事件、延时事件

Netty的任务队列是一个基于优先级的任务队列,支持两种类型的任务:用户任务(User Task)和IO任务(IO Task)。
用户任务是由用户提交的,而IO任务是由Netty内部生成的,用于处理IO事件。
TaskQueue通过优先级队列实现,确保了高优先级的任务能够优先得到处理。

为了避免阻塞当前I/O线程,建议使用专门的EventLoopExecutor来处理长时间运行的任务或需要阻塞的操作 ,
每个EventLoop都有自己的任务队列,独立于其他EventLoop,这样可以确保任务的执行不会相互干扰。

Execute task in EventLoop

while (!terminated) {
    // 1 阻塞直到有事件可以运行
    List< Runnable> readyEvents = blockUntilEventsReady();
    for (Runnable ev: readyEvents) {
        // 2 循环所有事件,并运行他们
        ev.run(); 
    }
}


select() 阻塞方法,监听网络事件 processSelectedKeys() 分发处理网络事件 this.runAllTasks() 执行队列里面的任务
public final class NioEventLoop extends SingleThreadEventLoop { private Selector selector; // 多路选择器 private final Queue< Runnable> taskQueue; // 普通任务队列 PriorityQueue < ScheduledFutureTask < ? > > scheduledTaskQueue; // 定时任务队列 private volatile int ioRatio = 50; // 执行网络事件和任务队列的时间比例 protected void run() { int selectCnt = 0; for (;;) { final long ioStartTime = System.nanoTime(); try { processSelectedKeys(); // 执行网络事件 } finally { // Ensure we always run tasks. final long ioTime = System.nanoTime() - ioStartTime; ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio);//执行普通事件+定时事件 }}}} protected boolean runAllTasks(long timeoutNanos) { // 从定时任务队列里取出任务放入普通任务队列 fetchFromScheduledTaskQueue(); // 从任务队列中取出待执行任务 Runnable task = pollTask(); // 算出这里可以执行任务的时间 final long deadline = timeoutNanos > 0 ? ScheduledFutureTask.nanoTime() + timeoutNanos : 0; long runTasks = 0; long lastExecutionTime; for (;;) { // 开始执行任务,这里捕捉了任务异常 safeExecute(task); runTasks ++; // 每执行0x3F=64个任务开始检测超时 if ((runTasks & 0x3F) == 0) { lastExecutionTime = ScheduledFutureTask.nanoTime(); if (lastExecutionTime >= deadline) { break; } } task = pollTask(); // 取下一个任务,没有任务,记录时间后退出 if (task == null) { lastExecutionTime = ScheduledFutureTask.nanoTime(); break; } } this.lastExecutionTime = lastExecutionTime; return true; }
无锁化 每一个channel绑定一个线程,对channel的操作都放在这个线程中执行 多个线程写入channel 判断当前线程是否为事件循环线程, 如果不是,将操作封装为 runnable 或 callable 对象 ,放入channel绑定的事件循环的任务队列中执行

上一篇     下一篇
netty ByteBuf 种类

netty ByteToMessageDecoder

netty解码器实例

netty VS mina

热锅冷油,炒菜不粘锅的科学原理

netty Event Handler 和 Pipeline