Netty 的线程模型

Reactor 单线程模型:是指所有的IO操作都在同一个NIO线程上面完成,NIO线程负责:

作为NIO服务端,接收客户端的TCP连接

作为NIO客户端,向服务端发起TCP请求

读取通信对端的请求或者应答消息

向通信对端发送请求或应答消息

由于Reactor模式使用的是异步非阻基I/O,所有的I/O 操作都不会导致阻塞,理论上一个线程可以独立处理所有I/O相关的操作。从架构层面看,一个NIO线程确实可以完成其承担的职责。 例如,通过 Acceptor 类接收客户端的TCP 连接请求消息,当链路建立成功之后,通过Dispatch 将对应的 ByteBuffer 派发到指定的 Handler上,进行消息解码,用户线程消息编码后通过NIO 线程将消息发送给客户端。

在一些小容量应用场景下,可以使用单线程模型。 但是这对于高负载、大并发的应用场景却不合适,主要原因如下:

1:一个NIO线程同时处理成百上千的链路,性能上无法支撑,即便NIO线程的CPU负荷达到 100%,也无法满足海量消息的编码、解码、读取和发送。

2:当NIO 线程负载过重之后,处理速度将变慢,这会导致大量客户端连接超时,超时之后往往会进行重发,这更加重了NIO线程的负载,最终会导致大量消息积压和处理超时, 成为系统的性能瓶颈

3:可靠性问题:一旦NIO线程意外跑飞,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障

为了解决这些问题,演进出了Reactor多线程模型

Reactor多线程模型与单线程模型最大的区别就是有一组NIO 线程来处理IO操作

Reactor多程模型的特点如下:

1:有专门一个NIO线程——Acceptor 线程用于监听服务端,接收客户端的 TCP连接请求

2:网络I/O操作——读、写等由一个NIO 线程池负责,线程池可以采用标准的 JDK线程池实现,它包含一个任务队列和N个可用的线程,由这些 NIO 线程负责消息的读取、解码、编码和发送

3:一个NIO 线程可以同时处理N条链路,但是一个链路只对应一个NIO线程, 防止发生并发操作问题

  

   在绝大多数场景下,Reactor 多线程模型可以满足性能需求,但是 在个特殊场景中,一个NIO线程负责监听和处理所有的客户端连接可能会仔在性能问题,例如并发百万客户端连接,或者服务端需要对客户端握手进行安全认证,但是认证本身非常损耗性能。在这类场景下,单独一个 Acceptor 线程可能会存在性能个足的问题,为了解决性能问题,产生了第三种Reactor线程模型——主从Reactor多线程模型。

主从Reactor多线程模型

主从Reactor线程模型的特点是:服务端用于接收客户端连接的不再是一个单独的NIO线程,而是一个独立的NIO 线程池。Acceptor 接收到客户端 TCP 连接请求并处理完成后(可能包含接入认证等),将新创建的 SocketChannel注册到I/O线程池(sub reactor 线程池)的某个I/0线程上,由它负责SocketChannel 的读写和编解码工作。Acceptor 线程池仅仅用于客户端的登录、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的IO线程上,由IO负责后续的IO操作。

利用主从NIO线程模型,可以解决一个服务端监听线程无法有效处理所有客户端连接的性能不足的问题,因为在Netty的官网Demo中,推荐使用该线程模型

发布了50 篇原创文章 · 获赞 2 · 访问量 2316

猜你喜欢

转载自blog.csdn.net/eafun_888/article/details/96567707