|
1 |
| - |
2 | 1 | ## Netty 的线程模型
|
3 |
| -Netty线程模型 的设计,也是基于 Reactor模型,尽管不同的 NIO框架 对于 Reactor模式 的实现存在差异,但本质上还是遵循了 Reactor 的基础线程模型。 |
4 | 2 |
|
| 3 | +Netty 线程模型 的设计,也是基于 Reactor 模型,尽管不同的 NIO 框架 对于 Reactor 模式 的实现存在差异,但本质上还是遵循了 Reactor 的基础线程模型。 |
5 | 4 |
|
6 | 5 | #### Reactor 单线程模型
|
7 |
| -Reactor单线程模型,是指所有的 I/O操作 都在同一个 NIO线程 上完成。NIO线程 的职责如下。 |
8 |
| -1. 作为 NIO服务端,接收客户端的 TCP连接; |
9 |
| -2. 作为 NIO客户端,向服务端发起 TCP连接; |
| 6 | + |
| 7 | +Reactor 单线程模型,是指所有的 I/O 操作 都在同一个 NIO 线程 上完成。NIO 线程 的职责如下。 |
| 8 | + |
| 9 | +1. 作为 NIO 服务端,接收客户端的 TCP 连接; |
| 10 | +2. 作为 NIO 客户端,向服务端发起 TCP 连接; |
10 | 11 | 3. 读取通信对端的请求或者应答消息;
|
11 | 12 | 4. 向通信对端发送消息请求或者应答消息。
|
12 | 13 |
|
13 |
| -理论上一个 NIO线程 可以独立处理所有 I/O操作。例如,通过 Acceptor类 接收客户端的 TCP连接,链路建立成功后,通过 Dispatch 轮询事件就绪的 Channel,将事件分发到指定的 Handler 上进行事件处理。小容量应用场景下,可以使用单线程模型。但对于高负载、大并发的应用场景并不合用。 |
| 14 | +理论上一个 NIO 线程 可以独立处理所有 I/O 操作。例如,通过 Acceptor 类 接收客户端的 TCP 连接,链路建立成功后,通过 Dispatch 轮询事件就绪的 Channel,将事件分发到指定的 Handler 上进行事件处理。小容量应用场景下,可以使用单线程模型。但对于高负载、大并发的应用场景并不合用。 |
14 | 15 |
|
15 | 16 | #### Reactor 多线程模型
|
16 |
| -Rector多线程模型 与 单线程模型 最大的区别就是有一组 NIO线程 来处理 I/O操作,Reactor多线程模型 的特点如下。 |
17 |
| -1. 有专门一个 NIO线程 (Acceptor线程) 用于监听服务端,接收客户端的 TCP连接请求。 |
18 |
| -2. 网络IO操作 由一个 NIO线程池 负责,由这些 NIO线程 负责消息的 读取、解码、编码、发送。 |
19 |
| -3. 一个 NIO线程 可以同时处理 N条链路,但是一个链路只对应一个 NIO线程,防止发生并发操作问题。 |
20 | 17 |
|
21 |
| -Reactor多线程模型 可以满足大部分场景的需求。但对于 百万级超高并发 或 服务端需要对客户端进行安全认证,但认证非常消耗资源。在这类场景下,单独一个 Acceptor线程 可能会处理不过来,成为系统的性能瓶颈。 |
| 18 | +Rector 多线程模型 与 单线程模型 最大的区别就是有一组 NIO 线程 来处理 I/O 操作,Reactor 多线程模型 的特点如下。 |
| 19 | + |
| 20 | +1. 有专门一个 NIO 线程 (Acceptor 线程) 用于监听服务端,接收客户端的 TCP 连接请求。 |
| 21 | +2. 网络 IO 操作 由一个 NIO 线程池 负责,由这些 NIO 线程 负责消息的 读取、解码、编码、发送。 |
| 22 | +3. 一个 NIO 线程 可以同时处理 N 条链路,但是一个链路只对应一个 NIO 线程,防止发生并发操作问题。 |
| 23 | + |
| 24 | +Reactor 多线程模型 可以满足大部分场景的需求。但对于 百万级超高并发 或 服务端需要对客户端进行安全认证,但认证非常消耗资源。在这类场景下,单独一个 Acceptor 线程 可能会处理不过来,成为系统的性能瓶颈。 |
22 | 25 |
|
23 | 26 | #### Reactor 主从多线程模型
|
24 |
| -主从Reactor多线程模型的特点是,服务端用于接收客户端连接的是一个独立的 NIO线程池。**Acceptor线程 与客户端建立 TCP连接 后,将新的 SocketChannel 注册到 NIO线程池 的某个 NIO线程 上,由该 NIO线程 负责轮询 SocketChannel 上的 IO事件,并进行事件处理**。 |
| 27 | + |
| 28 | +主从 Reactor 多线程模型的特点是,服务端用于接收客户端连接的是一个独立的 NIO 线程池。**Acceptor 线程 与客户端建立 TCP 连接 后,将新的 SocketChannel 注册到 NIO 线程池 的某个 NIO 线程 上,由该 NIO 线程 负责轮询 SocketChannel 上的 IO 事件,并进行事件处理**。 |
25 | 29 |
|
26 | 30 | 利用 主从多线程模型,可以解决一个服务端监听线程无法有效处理所有客户端连接的性能不足问题。在 Netty 的官方 Demo 中,也是推荐使用该线程模型。
|
27 | 31 |
|
28 | 32 | #### Netty 多线程编程最佳实践
|
29 |
| -1. **如果业务逻辑比较简单,并且没有 数据库操作、线程阻塞的磁盘操作、网路操作等,可以直接在 NIO线程 上完成业务逻辑编排,不需要切换到用户线程;** |
30 |
| -2. **如果业务逻辑比较复杂,不要在 NIO线程 上完成,建议将解码后的 POJO消息 封装成 Task,分发到 业务线程池 中由业务线程执行,以保证 NIO线程 尽快被释放,处理其他的I/O操作。** |
| 33 | + |
| 34 | +1. **如果业务逻辑比较简单,并且没有 数据库操作、线程阻塞的磁盘操作、网路操作等,可以直接在 NIO 线程 上完成业务逻辑编排,不需要切换到用户线程;** |
| 35 | +2. **如果业务逻辑比较复杂,不要在 NIO 线程 上完成,建议将解码后的 POJO 消息 封装成 Task,分发到 业务线程池 中由业务线程执行,以保证 NIO 线程 尽快被释放,处理其他的 I/O 操作。** |
31 | 36 | 3. **由于用户场景不同,对于一些复杂系统,很难根据 理论公式 计算出最优线程配置,只能是 结合公式给出一个相对合理的范围,然后对范围内的数据进行性能测试,选择相对最优配置。**
|
32 | 37 |
|
33 | 38 | ## NioEventLoop 源码解析
|
@@ -94,7 +99,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
94 | 99 | }
|
95 | 100 | }
|
96 | 101 | }
|
97 |
| - |
| 102 | + |
98 | 103 | /**
|
99 | 104 | * 轮询 事件就绪的channel,进行 IO事件处理
|
100 | 105 | */
|
@@ -153,4 +158,4 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
153 | 158 | }
|
154 | 159 | }
|
155 | 160 | }
|
156 |
| -``` |
| 161 | +``` |
0 commit comments