IO设计模式:Reactor和Proactor对比

平时接触的开源产品如Redis、ACE,事件模型都使用的Reactor模式;而一样作事件处理的Proactor,因为操做系统的缘由,相关的开源产品也少;这里学习下其模型结构,重点对比下二者的异同点;编程

反应器Reactor

Reactor模式结构

241052434069024.jpg

Reactor包含以下角色:windows

  • Handle 句柄;用来标识socket链接或是打开文件;
  • Synchronous Event Demultiplexer:同步事件多路分解器:由操做系统内核实现的一个函数;用于阻塞等待发生在句柄集合上的一个或多个事件;(如select/epoll;)
  • Event Handler:事件处理接口
  • Concrete Event HandlerA:实现应用程序所提供的特定事件处理逻辑;
  • Reactor:反应器,定义一个接口,实现如下功能:
    1)供应用程序注册和删除关注的事件句柄;
    2)运行事件循环;
    3)有就绪事件到来时,分发事件到以前注册的回调函数上处理;

“反应”器名字中”反应“的由来:数组

“反应”即“倒置”,“控制逆转”服务器

具体事件处理程序不调用反应器,而是由反应器分配一个具体事件处理程序,具体事件处理程序对某个指定的事件发生作出反应;这种控制逆转又称为“好莱坞法则”(不要调用我,让我来调用你)多线程

业务流程及时序图

241052444538838.jpg

  1. 应用启动,将关注的事件handle注册到Reactor中;
  2. 调用Reactor,进入无限事件循环,等待注册的事件到来;
  3. 事件到来,select返回,Reactor将事件分发到以前注册的回调函数中处理;

Proactor模式

Proactor模式结构

241052458282851.jpg

Proactor主动器模式包含以下角色架构

  • Handle 句柄;用来标识socket链接或是打开文件;
  • Asynchronous Operation Processor:异步操做处理器;负责执行异步操做,通常由操做系统内核实现;
  • Asynchronous Operation:异步操做
  • Completion Event Queue:完成事件队列;异步操做完成的结果放到队列中等待后续使用
  • Proactor:主动器;为应用程序进程提供事件循环;从完成事件队列中取出异步操做的结果,分发调用相应的后续处理逻辑;
  • Completion Handler:完成事件接口;通常是由回调函数组成的接口;
  • Concrete Completion Handler:完成事件处理逻辑;实现接口定义特定的应用处理逻辑;

业务流程及时序图

241052468598435.jpg

  1. 应用程序启动,调用异步操做处理器提供的异步操做接口函数,调用以后应用程序和异步操做处理就独立运行;应用程序能够调用新的异步操做,而其它操做能够并发进行;
  2. 应用程序启动Proactor主动器,进行无限的事件循环,等待完成事件到来;
  3. 异步操做处理器执行异步操做,完成后将结果放入到完成事件队列;
  4. 主动器从完成事件队列中取出结果,分发到相应的完成事件回调函数处理逻辑中;

对比二者的区别

主动和被动

以主动写为例:并发

  • Reactor将handle放到select(),等待可写就绪,而后调用write()写入数据;写完处理后续逻辑;
  • Proactor调用aoi_write后马上返回,由内核负责写操做,写完后调用相应的回调函数处理后续逻辑;

能够看出,Reactor被动的等待指示事件的到来并作出反应;它有一个等待的过程,作什么都要先放入到监听事件集合中等待handler可用时再进行操做;
Proactor直接调用异步读写操做,调用完后马上返回;异步

实现

Reactor实现了一个被动的事件分离和分发模型,服务等待请求事件的到来,再经过不受间断的同步处理事件,从而作出反应;socket

Proactor实现了一个主动的事件分离和分发模型;这种设计容许多个任务并发的执行,从而提升吞吐量;并可执行耗时长的任务(各个任务间互不影响)函数

优势

Reactor实现相对简单,对于耗时短的处理场景处理高效;
操做系统能够在多个事件源上等待,而且避免了多线程编程相关的性能开销和编程复杂性;
事件的串行化对应用是透明的,能够顺序的同步执行而不须要加锁;
事务分离:将与应用无关的多路分解和分配机制和与应用相关的回调函数分离开来,

Proactor性能更高,可以处理耗时长的并发场景;

缺点

Reactor处理耗时长的操做会形成事件分发的阻塞,影响到后续事件的处理;

Proactor实现逻辑复杂;依赖操做系统对异步的支持,目前实现了纯异步操做的操做系统少,实现优秀的如windows IOCP,但因为其windows系统用于服务器的局限性,目前应用范围较小;而Unix/Linux系统对纯异步的支持有限,应用事件驱动的主流仍是经过select/epoll来实现;

适用场景

Reactor:同时接收多个服务请求,而且依次同步的处理它们的事件驱动程序;
Proactor:异步接收和同时处理多个服务请求的事件驱动程序;

参考

《面向模式的软件体系结构 卷2》
《面向模式的软件架构 卷4》

Posted by: 大CC | 28APR,2015
博客:blog.me115.com [订阅]
微博:新浪微博