关于Reactor和Proactor的差别
/*********************************************************************
* Author : Samson
* Date : 07/12/2015
* Test platform:
* gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
* GNU bash, 4.3.11(1)-release (x86_64-pc-linux-gnu)
* Nginx version:
* Nginx 1.6.2
* Nginx 1.8.0
* *******************************************************************/
系统I/O 可分为堵塞型。 非堵塞同步型以及非堵塞异步型。
堵塞型I/O意味着控制权仅仅到调用操作结束了才会回到调用者手里。
非堵塞同步是会马上返回控制权给调用者的。
调用者不须要等等。它从调用的函数获取两种结果:要么此次调用成功进行了;要么系统返回错误标识告诉调用者当前资源不可用,你再等等或者再试度看吧。比方read()操作。 假设当前socket无数据可读,则马上返回EWOULBLOCK/EAGAIN,告诉调用read()者”数据还没准备好,你稍后再试”。
非堵塞异步调用中,稍有不同。调用函数在马上返回时,还告诉调用者。这次请求已经開始了。系统会使用另外的资源或者线程来完毕这次调用操作。并在完毕的时候知会调用者(比方通过回调函数)。POSIX的aio_read()来说。调用它之后,函数马上返回,操作系统在后台同一时候開始读操作。即是将工作交给了内核去完毕这个操作。
在以上三种IO形式中。非堵塞异步是性能最高、伸缩性最好的。
两种IO多路复用方案:Reactor and Proactor
普通情况下,I/O 复用机制须要事件分享器(event demultiplexor)。 事件分享器的作用,即将那些读写事件源分发给各读写事件的处理者。就像送快递的在楼下喊: 谁的什么东西送了, 快来拿吧。
开发者在開始的时候须要在分享器那里注冊感兴趣的事件。并提供对应的处理者(event handlers),或者是回调函数; 事件分享器在适当的时候会将请求的事件分发给这些handler或者回调函数。
涉及到事件分享器的两种模式称为:Reactor and Proactor。 Reactor模式是基于同步I/O的,而Proactor模式是和异步I/O相关的。
在Reactor模式中,事件分离者等待某个事件或者可应用或个操作的状态发生(比方文件描写叙述符可读写。或者是socket可读写),事件分离者就把这个事件传给事先注冊的事件处理函数或者回调函数,由后者来做实际的读写操作。
而在Proactor模式中。事件处理者(或者代由事件分离者发起)直接发起一个异步读写操作(相当于请求),而实际的工作是由操作系统来完毕的。发起时。须要提供的參数包含用于存放读到数据的缓存区,读的数据大小,或者用于存放外发数据的缓存区,以及这个请求完后的回调函数等信息。事件分离者得知了这个请求,它默默等待这个请求的完毕,然后转发完毕事件给对应的事件处理者或者回调。
这样的异步模式的典型实现是基于操作系统底层异步API的。所以我们可称之为“系统级别”的或者“真正意义上”的异步。由于详细的读写是由操作系统代劳的。
举另外个样例来更好地理解Reactor与Proactor两种模式的差别。这里我们仅仅关注read操作。由于write操作也是差点儿相同的。
以下是Reactor的做法:
某个事件处理者宣称它对某个socket上的读事件非常感兴趣;
事件分离者等着这个事件的发生;
当事件发生了,事件分离器被唤醒,这负责通知先前那个事件处理者;
事件处理者收到消息,于是去那个socket上读数据了。 假设须要,它再次宣称对这个socket上的读事件感兴趣,一直反复上面的步骤;
以下再来看看真正意义的异步模式Proactor是怎样做的:
事件处理者直接投递发一个写操作(当然,操作系统必须支持这个异步操作)。 这个时候。事件处理者根本不关心读事件,它仅仅管发这么个请求,它魂牵梦萦的是这个写操作的完毕事件。
这个处理者非常拽,发个命令就无论详细的事情了。仅仅等着别人(系统)帮他搞定的时候给他回个话。
事件分离者等着这个读事件的完毕(比較下与Reactor的不同);
当事件分离者默默等待完毕事情到来的同一时候,操作系统已经在一边開始干活了,它从目标读取数据,放入用户提供的缓存区中。最后通知事件分离者,这个事情我搞完了;
事件分享者通知之前的事件处理者: 你吩咐的事情搞定了;
事件处理者这时会发现想要读的数据已经乖乖地放在他提供的缓存区中,想怎么处理都行了。假设有须要。事件处理者还像之前一样发起另外一个写操作,和上面的几个步骤一样。
标准的经典的 Reactor模式:
步骤 1) 等待事件 (Reactor 的工作)
步骤 2) 发”已经可读”事件发给事先注冊的事件处理者或者回调 ( Reactor 要做的)
步骤 3) 读数据 (用户代码要做的)
步骤 4) 处理数据 (用户代码要做的)
模拟的Proactor模式:
步骤 1) 等待事件 (Proactor 的工作)
步骤 2) 读数据(看。这里变成成了让 Proactor 做这个事情)
步骤 3) 把数据已经准备好的消息给用户处理函数,即事件处理者(Proactor 要做的)
步骤 4) 处理数据 (用户代码要做的)
在没有底层异步I/O API支持的操作系统。这样的方法能够帮我们隐藏掉socket接口的差异(不管是性能还是其他)。 提供一个全然可用的统一“异步接口”。这样我们就能够开发真正平台独立的通用接口了。
那么,综上所述,这两者的差别是什么呢?
简单直观的理解:
1、Reactor模式是等待关心的动作的发生后。将怎样处理这个动作的兴许交给了用户态的应用本身来处理。Reactor的事件分享器仅仅关心事件的发生。其他的就全然交给应用程序来处理了;而Proactor模式则是仅仅关心由操作系统(内核)完毕异步非堵塞的操作后返回的结果。
2、Proactor场景中仅仅可以使用异步非堵塞的syscall(系统调用)。而Reactor的场景中很多其它地是使用非堵塞同步的syscall(系统调用);
对于不明确
IO - 同步,异步,堵塞,非堵塞概念的请先看下这个科普:
http://blog.csdn.net/historyasamirror/article/details/5778378
REF:
关于Reactor和Proactor的差别的更多相关文章
- 【转】Reactor与Proactor两种模式区别
转自:http://www.cnblogs.com/cbscan/articles/2107494.html 两种IO多路复用方案:Reactor and Proactor 一般情况下,I/O 复用机 ...
- 【Network】一张图看懂 Reactor 与 Proactor 模型的区别
首先来看看Reactor模式,Reactor模式应用于同步I/O的场景.我们以读操作为例来看看Reactor中的具体步骤:读取操作:1. 应用程序注册读就需事件和相关联的事件处理器2. 事件分离器等待 ...
- IO设计模式:Reactor和Proactor对比
IO设计模式:Reactor和Proactor对比 平时接触的开源产品如Redis.ACE,事件模型都使用的Reactor模式:而同样做事件处理的Proactor,由于操作系统的原因,相关的开源产品也 ...
- ACE_linux:Reactor与Proactor两种模式的区别
一.概念: Reactor与Proactor两种模式的区别.这里我们只关注read操作,因为write操作也是差不多的.下面是Reactor的做法: 某个事件处理器宣称它对某个socket上的读事件很 ...
- 【转载】高性能I/O设计模式Reactor和Proactor
转载自:http://blog.csdn.net/roger_77/article/details/1555170 昨天购买了<程序员>杂志 2007.4期,第一时间去翻阅了一遍,其中有一 ...
- 高性能IO设计的Reactor和Proactor模式(转)
在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作. 在比较这两个模式之前,我们首先的搞明白 ...
- 两种高性能 I/O 设计模式 Reactor 和 Proactor
两种高性能 I/O 设计模式 Reactor 和 Proactor Reactor 和 Proactor 是基于事件驱动,在网络编程中经常用到两种设计模式. 曾经在一个项目中用到了网络库 libeve ...
- Reactor和Proactor模式
在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作.同步和异步 同步和异步是针对应用程序和内 ...
- I/O模型系列之四:两种高性能IO设计模式 Reactor 和 Proactor
不同的操作系统实现的io策略可能不一样,即使是同一个操作系统也可能存在多重io策略,常见如linux上的select,poll,epoll,面对这么多不同类型的io接口,这里需要一层抽象api来完成, ...
随机推荐
- git与代码托管工具
1.git初识 git是一个版本管理工具,用来管理项目的不同的版本,记录下不同的提交记录,git还可以构建不同的分支,用来给不同的人来推送使用. 推荐的git教程:https://www.cnblog ...
- Python内置模块与标准库
Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...
- .NET下获取应用程序目录的一些方法
今天在Console Application下搞了一个小功能,期间需要获取当前应用程序的根目录,试了很多方式,都不能直接获取到,没有像Server.MapPath()这类的方法来方便地使用. 下面列举 ...
- System.Web.Routing入门及进阶 上篇
System.Web.Routing已经作为一个程序集包含在.net3.5sp1中发布了.虽然我们并没有在3.5sp1中发现Asp.net Mvc的踪迹,但是亦以感觉到它离我们不远了. System. ...
- [原创]win7环境下搭建eclipse+python+django开发环境
一)工具下载 a)eclipse(最新版4.3.1)官网下载地址 http://www.eclipse.org/downloads/ b)python (2.X版本)官网下载地址 http://pyt ...
- wpf 查找children的方法
var newValue = (bool)args.NewValue; HZWaitLoadingEx source = (HZWaitLoadingEx)sender; ControlTemplat ...
- final在类和方法中的使用
package final0; //final修饰的类不能继承//final修饰的方法不能继承public class TestFinal3 { public static void main(Str ...
- 了解一下LDC
转自: Linguistic Data Consortium (LDC) 因为Kaldi里面各种语料涉及到LDC,搜罗一下,好像并没有相应的教程和网站用法.... 搞 NLP 的人经常会听到一个神秘的 ...
- 004.Autofs自动挂载
一 安装autofs [root@imxhy data]# yum -y install autofs 二 编辑自动挂载相关配置 2.1 修改master [root@imxhy ~]# vi /et ...
- c#double类型保留百分号后两位,且禁止四舍五入的方法
double percent = Convert.ToDouble(50002.3) / Convert.ToDouble(50002.5) - 0.00005; string result = pe ...