服务端如何处理请求:后端接收到一个请求,简化下会做以下四个操作:
- 建立连接
- 读取数据
- 业务操作
- 写回数据
Reactor的核心思想:Reactor
模式也叫 Dispatcher
模式,将关注的IO事件注册到多路复用器上,一旦有IO事件触发,将事件分发到事件处理器中,执行就绪IO事件对应的处理函数中。模型中有三个重要的组件:
Reactor
:在一个单独的线程中运行,负责监听和分发事件,分发给适当的处理程序来对 IO 事件做出反应。Handlers
:处理程序执行IO事件要完成的实际事件,Reactor
通过调度处理程序来响应IO事件,处理程序执行非阻塞操作。
Reactor模式演进
Reactor
模型取决于 Reactor
的数量和 Hanndler
线程数量的不同,Reactor
模型有 3 个变种:
- 单线程
Reactor
模式:单Reactor
单线程Hanndler
- 多线程
Reactor
模式:单Reactor
多线程Hanndler
- 主从
Reactor
模式:主从Reactor
多线程Hanndler
Reactor
就是一个执行 while (true) { selector.select(); …}
循环的线程,会源源不断的产生新的事件,称作反应堆很贴切。
单线程Reactor
模式
单线程Reactor
模式 : 建立连接,读取/写回数据和业务操作都在同一个Reactor
线程中执行,虽然Reactor
的读取写回不会造成阻塞,但是业务操作就很可能造成阻塞;并且单线程不能充分利用CPU
多核优势,因此处理能力是有限的,对于小量连接情况下问题不大,对于大量链接情况下,单个NIO
线程因处理能力有限会导致连接大量超时。
多线程Reactor
模式
将非IO的业务逻辑操作从Reactor
线程上卸载,以此来加速Reactor
线程对IO请求的响应。
多线程Reactor
模式:多线程模式下把业务操作(decode
,compute
,encode
)等放到线程池中处理,保证Reactor
线程不会阻塞,而Reactor
仍为单个线程仍然要处理连接和读取/写回操作,其承担连接负载量上来时仍然承受很大压力(例如并发百万客户端连接,或者服务端需要对客户端握手进行安全认证,但是认证本身非常损耗性能)
主从Reactor
模式
主从Reactor
模式:相比多线程Reactor
模式,主从Reactor
模式下把IO读取/写回两个操作放在 从Reactor线程池 中执行, 主Reactor线程也就是Acceptor
只负责建立连接,建立之后将其注册到 从Reactor线程 中,因此大大提高了负载能力。同时为了避免并发问题还要保证一个连接只能注册一个Reactor
线程上
MainReactor
负责客户端的连接请求,并将请求转交给SubReactor
SubReactor
负责相应通道的IO读写操作- 非IO请求(具体逻辑处理)的任务则会交由工作线程池处理
好处:因为subReactor也会执行一些比较耗时的IO操作,例如消息的读写,使用多个线程去执行,则更加有利于发挥CPU的运算能力,减少IO等待时间。