目录
前言
Reactor线程模型不是Java专属,也不是Netty专属,它其实是一种并发编程模型,是一种思想,具有指导意义。
Reactor线程模型定义了三种角色:
- Reactor:负责监听和分配事件,将I/O事件分派给对应的Handler。新的事件包含连接建立就绪、读就绪、写就绪等。
- Acceptor:处理客户端新连接,并分派请求到处理器链中。
- Handler:将自身与事件绑定,执行非阻塞读/写任务,完成channel的读入,完成处理业务逻辑后,负责将结果写出channel。
Reactor线程的三种模型
Reactor [riˈæktə®] 反应堆,即IO多路复用模型。
三种模式用生活案例举例:
- 单Reactor单线程 :前台接待员和服务员都是同一个人,全程为顾客服务。
- 单Reactor多线程 :一个前台接待员,多个服务员,接待员只负责接待。
- 主从Reactor多线程 :多个前台接待员,多个服务生。
1. 单Reactor-单线程
所有的接收连接,处理数据的相关操作都在一个线程中来完成,性能上有瓶颈。
示意图:
1.1 流程分析
- Reactor对象通过select监控客户端请求事件,收到事件后通过Dispatch进行分发;
- 如果是建立连接请求事件,则由Acceptor通过accept处理连接请求,然后创建Handler对象处理连接完成后的后续业务处理;
- 如果不是建立连接请求事件,则Reactor则会分发调用连接对应的Handler来响应;
- Handler会完成Read->业务处理->Send的完整业务逻辑。
模式图如图所示:
1.2 优缺点
优点:
模型简单,没有多线程、进程通信、竞争的问题。
缺点:
性能问题,只有一个线程,无法发挥多核CPU的性能;
可靠性问题,线程意味终止或者进入死循环,会导致整个系统不可用。
1.3 使用场景
Redis的多路复用模型。
2. 单Reactor-多线程
把比较耗时的数据的编解码运算操作放入线程池中来执行,提升了性能但还不是最好的方式。
示意图:
2.1 流程分析
- Reactor对象通过select监控客户端请求,当请求事件达到后,通过dispatch分发请求;
- 若是建立连接的事件,则通过Acceptor的accept处理连接请求,然后创建Handler事件来处理后续逻辑;
- 如果不是建立连接事件,则通过Reactor分发到连接对应的handler来处理;
- handler只负责响应事件,不做具体的业务处理,通过read读取数据后,分发给worker线程池去处理业务;
- worker线程池会分配独立的线程去完成真正的业务,并将结果返回给handler;
- handler收到响应后,通过send方法将结果返回给client。
模式图如图所示:
2.2 优缺点
优点:可以充分利用多核CPU的能力;
缺点:多线程数据共享和访问比较复杂,reactor依旧是单线程去处理所有的事件监听和响应,在高并发下依旧存在性能问题。
3. 主从Reactor-多线程
主从多线程,对于服务器来说,接收客户端的连接是比较重要的,因此将这部分操作单独用线程去操作。
示意图:
3.1 流程分析
- Reactor 主线程 MainReactor 对象通过 select 监听客户端连接事件,收到事件后,通过 Acceptor 处理客户端连接事件;
- 当 Acceptor 处理完客户端连接事件之后(与客户端建立好 Socket 连接),MainReactor 将连接分配给SubReactor。(即:MainReactor 只负责监听客户端连接请求,和客户端建立连接之后将连接交由SubReactor 监听后面的 IO 事件。)
- SubReactor 将连接加入到自己的连接队列进行监听,并创建 Handler 对各种事件进行处理。
- 当连接上有新事件发生的时候,SubReactor 就会调用对应的 Handler 处理。
- Handler通过 read 从连接上读取请求数据,将请求数据分发给 Worker 线程池进行业务处理。
- Worker 线程池会分配独立线程来完成真正的业务处理,并将处理结果返回给 Handler。Handler 通过send 向客户端发送响应数据。
一个 MainReactor 可以对应多个 SubReactor,即一个 MainReactor 线程可以对应多个 SubReactor 线程。
模式图如图所示:
3.2 优缺点
优点:
- MainReactor 线程与 SubReactor 线程的数据交互简单职责明确,MainReactor 线程只需要接收新连接,SubReactor 线程完成后续的业务处理。
- MainReactor线程与SubReactor线程的数据交互简单,MainReactor线程只需要把新连接传给SubReactor线程,SubReactor 线程无需返回数据。
- 多个 SubReactor 线程能够应对更高的并发请求。
缺点:
是编程复杂度较高。
但是由于其优点明显,在许多项目中被广泛使用,包括 Nginx、Memcached、Netty 等。
这种模式也被叫做服务器的 1+M+N 线程模式,即使用该模式开发的服务器包含一个(或多个,1 只是表示相对较少)连接建立线程+M 个 IO 线程+N 个业务处理线程。这是业界成熟的服务器程序设计模式。
Reactor模式的优点
- 响应快,不必为单个同步事件所阻塞,虽然Reactor本身依然是同步的。
- 可以最大程度避免复杂的多线程及同步问题,并且避免多线程/进程的切换。
- 扩展性好,可以方便通过增加Reactor实例个数充分利用CPU资源。
- 复用性好,Reactor模型本身与具体事件处理逻辑无关,具有很高的复用性。
参考
[1]: https://www.jianshu.com/p/9a4624447f1b
[2]: https://blog.csdn.net/weixin_44471490/article/details/114606481