文档章节

服务器高效I/O设计模式

满小茂
 满小茂
发布于 2016/04/13 23:05
字数 1537
阅读 5931
收藏 198

前言

 

         一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器对象可将来自事件源的I/O事件分离出来,并分发到对应的read/write事件处理器(Event Handler)。开发人员预先注册需要处理的事件及其事件处理器(或回调函数);事件分离器负责将请求事件传递给事件处理器。两个与事件分离器有关的模式是Reactor和Proactor。Reactor模式采用同步IO,而Proactor采用异步IO。

      在Reactor中,事件分离器负责等待文件描述符或socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。

      在Proactor模式中,处理器--或者兼任处理器的事件分离器,只负责发起异步读写操作。IO操作本身由操作系统来完成。传递给操作系统的参数需要包括用户定义的数据缓冲区地址         和 数据大小,操作系统才能从中得到写出操作所需数据,或写入从socket读到的数据。事件分离器捕获IO操作完成事件,然后将事件传递给对应处理器。

       比如,在windows上,处理器发起一个异步IO操作,再由事件分离器等待IOCompletion事件。典型的异步模式实现,都建立在操作系统支持异步API的基础之上,我们将这种实现称为“系统级”异步或“真”异步,因为应用程序完全依赖操作系统执行真正的IO工作。

 

解释

    Reactor反应器:

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

    Proactor主动器:

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

 

两种模式的步骤

标准的经典的 Reactor模式

  • 步骤 1) 等待事件 (Reactor 的工作)
  • 步骤 2) 发”已经可读”事件发给事先注册的事件处理者或者回调 ( Reactor 要做的)

  • 步骤 3) 读数据 (用户代码要做的)

  • 步骤 4) 处理数据 (用户代码要做的)

Proactor模式

  • 步骤 1) 等待事件 (Proactor 的工作)

  • 步骤 2) 读数据(看,这里变成成了让 Proactor 做这个事情,可用用操作系统的异步io函数,也可以用一个主线程来模拟异步io)

  • 步骤 3) 把数据已经准备好的消息给用户处理函数,即事件处理者(Proactor 要做的)

  • 步骤 4) 处理数据 (用户代码要做的)

     

 

对比两者的区别

主动和被动

以主动写为例:
       Reactor将handle放到select(),等待可写就绪,然后调用write()写入数据;写完处理后续逻辑;
       Proactor调用aoi_write后立刻返回,由内核负责写操作,写完后调用相应的回调函数处理后续逻辑;

 可以看出,Reactor被动的等待指示事件的到来并做出反应;它有一个等待的过程,做什么都要先放入到监听事件集合中等待handler可用时再进行操作;

     Proactor直接调用异步读写操作,调用完后立刻返回;

实现

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

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

优点

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

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

缺点

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

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

(Linux有对aio的支持,可以参照这篇文章:http://www.lenky.info/archives/2013/01/2183  linux native AIO与eventfd、epoll的结合使用);

适用场景

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

Proactor:异步接收和同时处理多个服务请求的事件驱动程序;

 

 

© 著作权归作者所有

共有 人打赏支持
满小茂
粉丝 73
博文 119
码字总数 131754
作品 0
成都
程序员
加载中

评论(15)

qinshuluye
qinshuluye
写的好
满小茂
满小茂

引用来自“Pader”的评论

前面说了那么多,到最后说白了就是异步单线程和同步多线程的区别,我也是醉了。另外BSD的kevent也不说一下非常失望。

这是两种模式,主要区别在数据读取交给用户还是系统,至于你怎么实现基于什么平台是你的事,
Pader
Pader
前面说了那么多,到最后说白了就是异步单线程和同步多线程的区别,我也是醉了。另外BSD的kevent也不说一下非常失望。
feiyu1993
feiyu1993
mark
满小茂
满小茂

引用来自“航海家”的评论

支持前摄器模式。
感觉boost asio(前摄器),比libevent(反应堆)好用。
各有所长,linux下的东西还是纯C的好
-土星-
-土星-
支持前摄器模式。
感觉boost asio(前摄器),比libevent(反应堆)好用。
满小茂
满小茂

引用来自“twist_fate”的评论

这两种io模式又没有做性能上的对比
性能上的对比就是优点缺点,这两种模式用的场景不一样,不能说谁好谁坏
走起来

引用来自“走起来”的评论

有些不明白, Proactor分发请求事件到工作线程, 这个工作线程是动态创建的么?

引用来自“满小茂”的评论

工作线程一般是程序初始化先创建好了的,实际开发中会把分发请求发到线程池去让线程池自己调度执行

引用来自“走起来”的评论

这个线程池调度,是找空闲工作线程, 还是固定线程哈?

引用来自“满小茂”的评论

这个看自己设计,一般是线程池自己找空闲线程,固定线程实现不太好
谢谢大咖这么有耐心, 受益多多!
twisted3
twisted3
这两种io模式又没有做性能上的对比
满小茂
满小茂

引用来自“走起来”的评论

有些不明白, Proactor分发请求事件到工作线程, 这个工作线程是动态创建的么?

引用来自“满小茂”的评论

工作线程一般是程序初始化先创建好了的,实际开发中会把分发请求发到线程池去让线程池自己调度执行

引用来自“走起来”的评论

这个线程池调度,是找空闲工作线程, 还是固定线程哈?
这个看自己设计,一般是线程池自己找空闲线程,固定线程实现不太好
编程中的那些经典套路——设计模式汇总

在正式阅读前,我先谈谈我们该用什么姿势和心态学习设计模式: 如果你还没有过多的编程经验(泛指半年以下),我建议你把它当做小说来看,能看懂多少是多少,因为半年以下经验的程序员用到设...

gzchen
08/27
0
0
设计模式学习笔记之-代理模式

代理模式中,客户不会直接调用目标对象而是通过一个代码对象,客户调用代理对象代理对象去调用目标对象,起到对象与对象间的隔离作用。有时候我么不想直接访问目标对象,有时候我们不能直接访...

申文波
03/05
0
0
企业开发珠玑-什么时候使用设计模式

一、我们必须明白一点:设计模式仅仅是个称呼,目标是方便交流记忆。中心点是什么?方便交流记忆,仅仅是个词语,和汉语词典里面的一个词也没什么区别。---------没什么高大上的东西,不怕 ...

fir01
2015/08/24
0
0
编程中的那些套路——关于策略模式

该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天讲讲策略模式,策略模式 和工厂模式十分相像(或者说在代码逻辑层面,他们是一样的)。 但策略模式与...

gzchen
08/27
0
0
Android拓展系列(4)--vim编辑器的基本使用

从接触Linux到现在,也已经好几年了,对于linux的感觉一直是分分离离,充满了遗憾,最大的遗憾之一就是一直没能精通vim,不能完全适应vim下的代码开发。 最近工作中又广泛接触到vim的使用,我...

枫影Xda
2011/10/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

idea 通过jpa自动生成实体类

引入jpa包 打开persistence窗口 右键选择连接数据库 如果数据库没配置,则可以在下图选项中配置 选择好数据库和实体类的生成地址

斩神魂
29分钟前
1
0
tcpdump 命令

TCPDUMP简介 tcpdump 是一个很常用的网络包分析工具,可以用来显示通过网络传输到本系统的 TCP/IP 以及其他网络的数据包。tcpdump 使用 libpcap 库来抓取网络报,这个库在几乎在所有的 Linu...

寰宇01
36分钟前
2
0
软件的Alpha、Beta、RC、GA版本的区别

Alpha:是内部测试版,一般不向外部发布,会有很多Bug.一般只有测试人员使用。 Beta:也是测试版,这个阶段的版本会一直加入新的功能。在Alpha版之后推出。 RC:(Release Candidate) 顾名思义...

乔老哥
38分钟前
2
0
慢雾安全海贼王:从DApp亡灵军团,细说区块链安全

本文转载自微信公号“万向区块链”,为慢雾安全负责人海贼王在万向区块链实验室举办的2018上海区块链国际周-技术开放日上的演讲速记整理。 这张图总结了智能合约攻防的各个方面,分为两大部分...

万向区块链
43分钟前
13
0
Matlab编程之——卷积神经网络CNN代码解析

卷积神经网络CNN代码解析 deepLearnToolbox-master是一个深度学习matlab包,里面含有很多机器学习算法,如卷积神经网络CNN,深度信念网络DBN,自动编码AutoE ncoder(堆栈SAE,卷积CAE)的作...

酒逢知己千杯少
44分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部