Reactor模型详解

NIO与Reactor模型关系

NIO是非阻塞IO,而Reactor是基于NIO的一种设计模式。NIO是一种模型,一种思想,使用NIO实现。下面看Reactor模型具体设计。

单 Reactor 单线程模式

在这里插入图片描述

  1. 可以实现通过一个阻塞对象监听多个链接请求
  2. Reactor对象通过select监听客户端请求事件,通过dispatch进行分发
  3. 如果是建立链接请求,则由Acceptor通过accept处理链接请求,然后创建一个Handler对象处理完成链接后的各种事件
  4. 如果不是链接请求,则由Reactor分发调用链接对应的Handler来处理
  5. Handler会完成Read->业务处理->send的完整业务流程

缺点:
当其中某个 handler 阻塞时, 会导致其他所有的 client 的 handler 都得不到执行, 并且更严重的是, handler 的阻塞也会导致整个服务不能接收新的 client 请求(因为 acceptor 也被阻塞了)。不能充分利用多核资源。
一个线程负载过重后,处理速度将变慢,这会导致大量客户端连接超时,超时之后往往会进行重发,这更加重了 NIO 线程的负载,最终会导致大量消息积压和处理超时,成为系统的性能瓶颈。
一旦 NIO 线程意外跑飞,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障。

单Reactor多线程模式

添加了一个工作者线程池,并将非 I/O 操作从 Reactor线程中移出转交给工作者线程池来执行。这样能够提高 Reactor 线程的 I/O 响应,不至于因为一些耗时的业务逻辑而延迟对后面 I/O 请求的处理。主要是将业务逻辑处理单独分出来线程执行,避免业务逻辑处理影响了I/O操作效率。
在这里插入图片描述

  1. Reactor对象通过select监听客户端请求事件,收到事件后,通过dispatch分发
  2. 如果是建立链接请求,则由Acceptor通过accept处理链接请求,然后创建一个Handler对象处理完成链接后的各种事件
  3. 如果不是链接请求,则由Reactor分发调用链接对应的Handler来处理
  4. Handler只负责事件响应不做具体业务处理
  5. 通过read读取数据后,分发到worker线程池处理,处理完成后返回给Handler,Handler收到后,通过send将结果返回给client

主从Reactor多线程

Reactor 线程池中的每一 Reactor 线程都会有自己的 Selector、线程和分发的事件循环逻
辑。mainReactor 可以只有一个,但 subReactor 一般会有多个。mainReactor 线程主要负责接收客户端的连接请求,然后将接收到的 SocketChannel 传递给 subReactor,由 subReactor 来完成和客户端的通信。
在这里插入图片描述

  1. Reactor主线程MainReactor对象通过select监听链接事件,通过Acceptor处理
  2. 当Acceptor处理链接事件后,MainReactor将链接分配给SubReactor
  3. SubReactor将链接加入到队列进行监听,并创建Handler进行事件处理
  4. 当有新事件发生时,SubReactor就会调用对应的Handler处理
  5. Handler通过read读取数据,分发到worker线程池处理,处理完成后返回给Handler,Handler收到后,通过send将结果返回给client
  6. Reactor主线程可以对应多个Reactor子线程

Reactor模型与观察者模式区别

观察者模式也可以称为为 发布-订阅 模式,主要适用于多个对象依赖某一个对象的状态并,当某对象状态发生改变时,要通知其他依赖对象做出更新。是一种一对多的关系。当然,如果依
赖的对象只有一个时,也是一种特殊的一对一关系。通常,观察者模式适用于消息事件处理,
监听者监听到事件时通知事件处理者对事件进行处理(这一点上面有点像是回调,容易与反
应器模式和前摄器模式的回调搞混淆)。
reactor 模式,即反应器模式,是一种高效的异步 IO 模式,特征是回调,当 IO 完成时,回调对应的函数进行处理。这种模式并非是真正的异步,而是运用了异步的思想,当 IO 事件触发时,通知应用程序作出 IO 处理。模式本身并不调用系统的异步 IO 函数。

reactor 模式与观察者模式有点像。不过,观察者模式与单个事件源关联,而反应器模式则与多个事件源关联 。当一个主体发生改变时,所有依属体都得到通知。

应用场景

Reactor模型通常用于网络模型中,进行连接、读操作、写操作且并发量高的服务中去进行I/O事件时使用。例如在redis中、nginx中,都使用了Reactor模型来实现客户端连接服务、读写数据的网络模型。当我们自己提供了一个服务,且有大量客户端与我们提供的服务进行I/O操作时,可以考虑使用Reactor模型进行I/O多路复用,来提高服务的I/O性能。

猜你喜欢

转载自blog.csdn.net/qq1309664161/article/details/128162911