反应器模式(Reactor Pattern)是一种为处理服务请求并发提交到一个或者多个服务处理程序的事件设计模式。反应器模式与观察都模式相似。但观察者模式与单个事件源关联,而反应器模式则与多个事件源关联。
先介绍两种高性能服务器模式Reactor、Proactor
这里用收快递作比喻。reactor
就像快速能收的时候,快递员会通知你拿快递。proactor
就像使用菜鸟驿站,内核
帮你代收了这个快递。
Reactor模型
在Reactor
中实现读:
1 向事件分发器注册事件回调
2 事件分发器等待事件
3 事件分发器调用之前注册的函数
4 在回调函数中读取数据,对数据进行后续处理Reactor
模型实例:libevent
,Redis
、ACE
。
Proactor模型
在Proactor
中实现读:
1 向事件分发器注册事件回调
2 事件分发器等待事件发生
3 操作系统读取数据,并放入应用缓冲区,然后通知事件分发器
4 事件分发器调用之前注册的函数
5 在回调函数中对数据进行后续处理
Preactor模型实例:ASIO。
reactor和proactor的主要区别
主动和被动
以主动写为例:Reactor
将handle
放到select()
,等待可写就绪,然后调用write()
写入数据;写完处理后续逻辑。Proactor
调用aoi_write
后立刻返回,由内核负责写操作,写完后调用相应的回调函数处理后续逻辑。
可以看出,Reactor
被动的等待指示事件的到来并做出反应;它有一个等待的过程,做什么都要先放入到监听事件集合中等待handler
可用时再进行操作。Proactor
直接调用异步读写操作,调用完后立刻返回。
实现
Reactor
实现了一个被动的事件分离和分发模型,服务等待请求事件的到来,再通过不受间断的同步处理事件,从而做出反应。Proactor
实现了一个主动的事件分离和分发模型,这种设计允许多个任务并发的执行,从而提高吞吐量,并可执行耗时长的任务(各个任务间互不影响)。
优点
Reactor
实现相对简单,对于耗时短的处理场景处理高效。操作系统可以在多个事件源上等待,并且避免了多线程编程相关的性能开销和编程复杂性。事件的串行化对应用是透明的,可以顺序的同步执行而不需要加锁。事务分离,将与应用无关的多路分解和分配机制和与应用相关的回调函数分离开来。
Proactor
性能更高,能够处理耗时长的并发场景。
缺点
Reactor
处理耗时长的操作会造成事件分发的阻塞,影响到后续事件的处理;Proactor
实现逻辑复杂。依赖操作系统对异步的支持,目前实现了纯异步操作的操作系统少,实现优秀的如windows IOCP
,但由于其windows
系统用于服务器的局限性,目前应用范围较小。而Unix/Linux
系统对纯异步的支持有限,应用事件驱动的主流还是通过select/epoll
来实现。
适用场景
Reactor
:同时接收多个服务请求,并且依次同步的处理它们的事件驱动程序。Proactor
:异步接收和同时处理多个服务请求的事件驱动程序。