IO设计模式:Reactor和Proactor对比

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

反应器Reactor

Reactor模式结构

Reactor包含如下角色:

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

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

业务流程及时序图

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

主动器Proactor

Proactor模式结构

Proactor主动器模式包含如下角色

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

业务流程及时序图

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

对比两者的区别

主动和被动

以主动写为例:
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:异步接收和同时处理多个服务请求的事件驱动程序;

类图和序列图的源文件提供下载,详见Github《图说设计模式》的EA文档:

https://github.com/me115/design_patterns

参考

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

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

IO设计模式:Reactor和Proactor对比的更多相关文章

  1. I/O模型系列之四:两种高性能IO设计模式 Reactor 和 Proactor

    不同的操作系统实现的io策略可能不一样,即使是同一个操作系统也可能存在多重io策略,常见如linux上的select,poll,epoll,面对这么多不同类型的io接口,这里需要一层抽象api来完成, ...

  2. I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor

    目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...

  3. 两种高性能 I/O 设计模式 Reactor 和 Proactor

    两种高性能 I/O 设计模式 Reactor 和 Proactor Reactor 和 Proactor 是基于事件驱动,在网络编程中经常用到两种设计模式. 曾经在一个项目中用到了网络库 libeve ...

  4. 【转载】高性能I/O设计模式Reactor和Proactor

    转载自:http://blog.csdn.net/roger_77/article/details/1555170 昨天购买了<程序员>杂志 2007.4期,第一时间去翻阅了一遍,其中有一 ...

  5. 转: IO设计模式:Reactor和Proactor对比

    转: https://segmentfault.com/a/1190000002715832 平时接触的开源产品如Redis.ACE,事件模型都使用的Reactor模式:而同样做事件处理的Proact ...

  6. 高性能I/O设计模式Reactor和Proactor

    系统I/O 可分为阻塞型, 非阻塞同步型,非阻塞异步型. (Linux对aio支持的不完整,所以linux上用Reactor比较多:Proactor需要系统API支持真正的“异步”) 阻塞型I/O意味 ...

  7. I/O模型之四:Java 浅析I/O模型(BIO、NIO、AIO、Reactor、Proactor)

    目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...

  8. 两种高性能I/O设计模式(Reactor/Proactor)的比较

    原文出处: Alex Libman   译文出处:潘孙友   欢迎分享原创到伯乐头条 综述 这篇文章探讨并比较两种用于TCP服务器的高性能设计模式. 除了介绍现有的解决方案,还提出了一种更具伸缩性,只 ...

  9. [转]两种高性能I/O设计模式(Reactor/Proactor)的比较

    [原文地址:http://www.cppblog.com/pansunyou/archive/2011/01/26/io_design_patterns.html] 综述 这篇文章探讨并比较两种用于T ...

随机推荐

  1. android 项目学习随笔八(xUtils的BitmapUtils模块)

    xUtils的BitmapUtils模块: 加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象: 支持加载网络图片和本地图片: 内存管 ...

  2. 161013、java实现邮件群发带附件

    要完成Java群发邮件功能,首先须加入mail.jar和activation.jar这两个包 下面是邮件的例子: import java.io.File; import java.util.Prope ...

  3. scala的apply方法

    package com.test.scala.test /** * apply 方法 */ object ApplyTest { def main(args: Array[String]): Unit ...

  4. SQLServer学习笔记<> 表连接查询----交叉连接、内连接、左连接、右连接

    (1)交叉连接(cross join)即我们所说的笛卡尔积.查询出满足两张表所有的记录数,A(3条记录),B(9条记录),A*B(27条记录). 比如:雇员表(HR.employees)和货运公司(S ...

  5. samba服务器源码安装(非rpm)

    首先我们创建一个文档,边安装配置samba,边写教程. 从www.samba.org下载samba最新源码包,我下载的是samba-3.0.7.tar.gz,把它放在我的目录的中/root/lova/ ...

  6. java 面试每日一题6

    题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1,2,3,5 ...

  7. (java)==和equals()的使用小结

    1.如果两个变量说基本数据类型,且都是数值类型,eg.65f,65(不一定要求数据类型严格相同),只要两个变量的值相等,就将返回true int it=65; float fl=65.0f; char ...

  8. c#游戏 剪刀石头

    电脑using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace sh ...

  9. 浪首登录浮层增加收藏入口项目学到的几点知识-IE7 bug、relatedTarget、字符串换行

    这两天做这个项目略有收获,记录如下: 1. 项目中有个bug,在IE7中登录成功时下拉菜单没有展开的情况下总有个残影在页面中,如下图所示: 通过多种方法都没有解决,后来才知道原来是在IE中displa ...

  10. A Simple Problem with Integers(树状数组HDU4267)

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (J ...