Netty的EventLoop和EventLoopGroup

Netty的EventLoop和EventLoopGroup教程

在前面的章节中,我们了解了 Reactor 模型的特点,以及大体讲了一下,Netty 对 Reactor 模型的支持,Netty 推荐使用主从多线程模型,有一个专门的线程用来接收 TCP 连接,另外有专门的线程用来处理 I/O 相关数据。EventLoopGroup 就很好的让 Netty 对 Reactor 支持。

NioEventLoop

NioEventLoop 是 EventLoop 的实现类,NioEventLoop 并不存粹是一个 I/O 线程,它除了负责 I/O 的读写之外,还兼顾处理一下子两种类型任务:

  • 系统 Task:通过调用 NioEventLoop 的 execute(Runnable task) 方法实现,Netty 有很多系统 Task,创建它们的主要原因是:当 I/O 线程和用户线程同时操作网络资源时,为了防止并发操作导致的锁竞争,将用户线程的擦走封装成 Task 放入消息队列中,由 I/O 线程负责执行,这样就可以实现局部无锁化。
  • 定时任务:通过调用 NioEventLoop 的 schedule(Runnable command,long delay,TimeUnit unit) 方法实现。

因为 NioEventLoop 需要处理网络 I/O 的读写事件,所以它必须聚合一个多路复用器对象,即 Selector。NioEventLoop 的执行逻辑是调用其 run 方法,run 方法里面是一个 for 的无限循环,只有当 NioEventLoop 接收到退出指令的时候,才会退出循环,不然的话会一直执行下去。

它在循环过程中,会先判断任务队列里面有没有需要处理的任务,如果有需要处理的任务就会从多路复用器上面获取相关任务,获取准备就绪的 Channel,然后结合 Channel 的 ChannelPipeline 进行相关处理。

EventLoopGroup

EventLoopGroup 是一组 EventLoop 的抽象,一个 EventLoopGroup 当中会包含一个或多个 EventLoop,EventLoopGroup 提供 next 接口,可以从一组 EventLoop 里面按照一定规则获取其中一个 EventLoop 来处理任务。

在 Netty 服务器端编程中我们需要 BossEventLoopGroup 和WorkerEventLoopGroup 两个 EventLoopGroup 来进行工作。

BossEventLoopGroup 通常是一个单线程的 EventLoop,EventLoop 维护着一个注册了 ServerSocketChannel 的 Selector 实例,EventLoop 的实现涵盖 IO 事件的分离,和分发(Dispatcher),EventLoop 的实现充当 Reactor 模式中的分发(Dispatcher)的角色。

所以通常可以将 BossEventLoopGroup 的线程数参数为 1。

BossEventLoop 只负责处理连接,故开销非常小,连接到来,马上按照策略将 SocketChannel 转发给 WorkerEventLoopGroup,WorkerEventLoopGroup 会由 next 选择其中一个 EventLoop 来将这 个SocketChannel 注册到其维护的 Selector 并对其后续的 IO 事件进行处理。

Netty的EventLoop和EventLoopGroup总结

  • NioEventLoopGroup 实际上就是个线程池,一个 EventLoopGroup 包含一个或者多个 EventLoop。
  • 一个 EventLoop 在它的生命周期内只和一个 Thread 绑定。
  • 所有有 EnventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理。
  • 一个 Channel 在它的生命周期内只注册于一个 EventLoop。
  • 每一个 EventLoop 负责处理一个或多个 Channel。