回答
EventLoop 是 Netty Reactor 线程模型的核心处理引擎,它是Netty 的事件循环机制的基础,它的本质我们理解为是一个单线程执行器。它具有如下特性和作用:
- 单线程模型:EventLoop 是单线程的,一个 EventLoop 绑定一个线程。在其生命周期内,它将处理所有分配给它的任务,也就是说在同一时间内,只有一个线程在处理所有的事件和任务。
- 事件循环:EventLoop 以循环的方式运行,持续检查并处理新的事件。这些事件包括网络 I/O 事件和用户定义的任务。循环确保每个事件都得到及时处理,同时保持了任务处理的顺序性。
- 任务调度:EventLoop 不仅可以处理 I/O 事件,还可以调度用户自定义的任务。
- 处理 Channel:每一个 Channel 都会分配给一个 EventLoop,在该 Channel 的生命周期内,该 Channel 的所有 I/O 操作都由与它绑定的 EventLoop 处理。
EventLoopGroup ,即 EventLoop 组,也就是说 EventLoopGroup 是一个包含多个 EventLoop 的集合,它负责管理这些 EventLoop。由于每个 EventLoop 都绑定到了一个线程上,所以 EventLoopGroup 也负责这些线程的生命周期管理。
在 Netty 中,通常情况下会有两个 EventLoopGroup:
Boss Group
:用于接受客户端的连接请求。一般只需要一个线程处理所有的连接请求。Worker Group
:用于处理与各个客户端之间的数据读写操作。通常会有多个线程,以处理大量的并发连接和数据传输。
扩展
EventLoop
EventLoop 是 Netty Reactor 线程模型的核心处理引擎。要想明白 Netty 为什么可以轻松处理成千上万规模的客户端连接,就必须要掌握 EventLoop。
EventLoop 从字面上来看就是 event + loop,也就是事件循环,事件就是 I/O 事件,循环则可以理解为 while(true)
。直白点就是EventLoop 是通过循环方式来处理 I/O 事件的执行器。它的简要 UML 类图如下:
从上面我们可以看出 EventLoop 本质就是一个单线程执行器,这个执行器干嘛呢?就是处理 Channel 上的 IO 事件。
当客户端与服务端建立连接后,服务端会创建一个 Channel,并将该 Channel 与 EventLoop 绑定。绑定后,该 Channel 在整个生命周期内所有发生的事件都由该 EventLoop 来处理,但是一个 EventLoop 可以绑定多个 Channel。对于 EventLoop 而言,它就是通过不断循环它所绑定的 Channel 事件列表,检测是否有事件发生,如果有,则将该事件分发给 worker 线程处理。运行模式如下图:
EventLoopGroup
EventLoopGroup 就是一组 EventLoop ,它主要是来维护和管理 EventLoop,一般我们是不会直接使用 EventLoop 的,而是通过 EventLoopGroup 来使用它。我们看 EventLoopGroup 的源码就知道 EventLoopGroup 就提供了两个方法:
register()
:当服务端创建一个 Channel 后,会调用 EventLoopGroup 的register()
将 Channel 绑定到其中一个 EventLoop 上。next()
:返回 EventLoopGroup 中维护的 EventLoop。
所以 Channel、EventLoop、EventLoopGroup 之间的关系如下:
- 一个 EventLoopGroup 包含一个或者多个 EventLoop。
- 一个 Channel 在它的声明周期中只会与一个 EventLoop 绑定。
- 一个 EventLoop 可以绑定多个 Channel。
- 一个 EventLoop 只会与一个 Thread 绑定,同时该 EventLoop 的所有 IO 事件都由这一个 Thread 执行。
如下图:
到这里我相信小伙伴们基本上知道了 EventLoop、EventLoopGroup 是干啥的了,他们的基本原理也差不多了解了,在上面 Reactor 线程模型中,大明哥提到,Netty 推荐我们采用主从多线程模型,这了大明哥就主从多线程模型把 Channel、EventLoop、EventLoopGroup 再阐述一遍,便于小伙伴们理解更深。先看图:
- BoosEventLoopGroup 负责监听客户端的 Accept 事件,当事件触发时,会新建一个 Channel,同时将 Channel 注册到 WorkEventLoopGroup 中的某个 EventLoop 上。
- WorkEventLoopGroup 中的 EventLoop 负责监听 Channel 的 read/write 事件,当有事件发生时,EventLoop 读取数据将交给与之绑定的 ChannelPipeline 的 ChannelHandler 处理。
- 这里有两个一一对应的关系
- 一个 Channel 对应一个 EventLoop,且整个生命周期内所有 IO 事件都是该 EventLoop 处理。
- 一个 EventLoop 对应一个 Thread,该 EventLoop 中的所有 IO 事件都由该 Thread 处理。
- 由于这两个一一对应的关系,Channel 生命周期的所有 IO 事件都是线程独立的。
我们在使用 EventLoop 的时候一般不会直接使用它,而是通过 EventLoopGroup 来使用,我们常用的 EventLoopGroup 有两种:
- NioEventLoopGroup:它处理IO事件、普通任务、定时任务
- DefaultEventLoopGroup:处理普通任务,定时任务