概述
Reactor 模型是基于事件驱动的线程模型,可以分为Reactor单线程模型、Reactor多线程模型、主从Reactor多线程模型,通常基于在I/O多路复用实现。角色职责:Dispatcher负责事件分发、Acceptor负责处理客户端连接、handler处理非连接事件(例如:读写事件)
三种Reactor线程模型
单线程Reactor模型
所有的IO操作都在同一个NIO线程池上面完成,职责如下:
- NIO服务端接受客户端的TCP连接
- 读取通信端的请求或者应答信息
- 向通信端发送消息或者应答消息
在一些小容量的应用场景下,可以使用单线程模型,但是对于高负载,大并发的应用场景不适合
- 一个NIO线程处理成百上千的线路,性能无法支撑,即便CPU跑满100%,单机也无法处理海量的消息
- NIO负载过重后,处理速度会很慢,导致大量的客户端连接超时,超时后重发,更加加重了NIO线程的负载。最终导致大量消息堆积,成为系统瓶颈
- 一旦NIO线程意外跑飞,会使整个系统通信模块不可用,不能接受和处理外部消息,造成节点故障
Reactor 多线程模型
多线程模型与单线程模型的最大区别就是有一组NIO线程来处理IO操作
- 一个专门的NIO线程-负载监听服务端,接收客户端的TCP连接请求
- 网络IO操作,读写等由另一个NIO线程池负责
- 一个NIO线程可以同时处理N条链路,但是一条链路只对应一个NIO线程,防止并发操作
大多数场景下,多线程模型是可以满足性能要求的,但是如果在百万并发链接中,客户端与服务端还要进行安全认证的工作,认证本身非常消耗性能,这种情况下Accept线程很可能存在性能不足的问题。
主从Reactor 多线程模型
这里服务端接受客户端的链接不在是一个单独的NIO线程,而是一个独立的NIO线程池,Acceptor连接请求并且处理完成后,将新创建的SocketChannel注册到IO线程池的某个IO线程上,Acceptor线程池仅仅用于客户端的认证,登录,握手工作,一旦链路建立成功,将链路注册到后端的IO线程池上去。
利用主从NIO线程模型,可以解决一个服务端监听线程无法有效处理所有客户端连接的性能不足问题,因此在大多数应用中,推荐使用这种线程模型