Reactor(反应器、反应堆)常用于网络编程。

Reactor框架

Reactor - 图1

  1. event demultiplexer

优点

Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:

  1. 响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;
  2. 编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
  3. 可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;
  4. 可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;

反应器设计模式与观察者模式在某些方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而反应器模式则与多个事件源关联 。

三种角色

  1. Reactor:负责监听和分配事件,将事件分派给对应的Handler。
  2. Acceptor:处理客户端新连接,并分派请求到处理器链中。
  3. Handler:将自身与事件绑定,执行非阻塞读/写任务。

image.png

示例一:船长与游客

「场景」假设有一艘飞船飞往太空旅行,飞船上有船长一名和游客若干。每位游客目的地并不一样,每位游客可以去若干个星球。在传统的模型中,游客需要一直等待,直到到达自己的目的地,这种做法会消耗游客的时间。因此,船长想了一个办法。

  1. 每个游客在上飞船之前,需要填一张目的地表,选上想要抵达的目的地,在上船的时候交给船长,然后就可以进入休眠舱休眠了。
  2. 船长在到达某一目的地后,会根据目的地表,筛选出对应的游客并唤醒,其他游客则继续休眠。这一模式下,游客不需要关心什么时候抵达,只需要被通知。

「抽象」这就是一个简易的Reactor模型
【】如果使用程序对上述案例进行抽象,每个游客到达目的地之后要做不同的动作,则该如何表达呢?
游客等待到达目星球地的过程,可以抽象为I/O的输入,或者是等待某一事件的触发。船长是Acceptor,游客(带门票)对应的模型是Reactor,抵达的目的地需要做的事情是Handler

【】抽象化这一流程的步骤如下:
1、定义Acceptor。Acceptor中定义多个事件,比如到达A星球事件、到达B星球事件等等。
2、定义AbstractReactor。AbstarctReactor对应这目的地表,包含了所有的目的地,每个目的地有对应的Handler,在目的地表中,是没有填的,因此代码中是空实现。
3、定义具体的Reactor。每一个游客抽象为一个不同的Reactor,每个游客勾选了不同的目的地,则是继承AbstarctReactor,并重写不同的接口。 每个Reactor可以有多个Handler。
4、重写具体Reactor中的Handler。比如游客甲到达A星球要做什么、到达B星球要做什么。游客乙到达C星球要干什么。
5、将Reactor加入到Acceptor中,让Acceptor管理。
6、飞船到达A星球,出发Acceptor中的到达A星球事件,此时船长需要唤醒了选了A星球的游客,对其发出通知。即Acceptor调用Reactor中的接口,触发Handler。
7、在完成之后,游客回到休眠舱,等待下一目的地,飞船继续航行。
以上步骤,还原了反应器从定义到实现的整个流程。

【】总的来说,Reactor实现相对简单,对于耗时短的处理场景处理高效;可以在多个事件源上等待,并且避免了多线程编程相关的性能开销和编程复杂性。

参考文章

  1. C++学习笔记(十六) - 典型的事件驱动设计模式-Reactor模式
  2. Reactor(反应器)模式初探