参考文档:

http://blog.csdn.net/u013074465/article/details/46276967

https://www.cnblogs.com/ivaneye/p/5731432.html

http://blog.csdn.net/Mrzhoug/article/details/51224624

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

Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发、高吞吐量的环境中进行I/O处理

reactor

uml类图



模式组成
  • 描述符(handle):由操作系统提供的资源,用于识别每一个事件,如Socket描述符、文件描述符、信号的值等。在Linux中,它用一个整数来表示。事件可以来自外部,如来自客户端的连接请求、数据等。事件也可以来自内部,如信号、定时器事件。
  • 同步事件多路分离器(event demultiplexer):事件的到来是随机的、异步的,无法预知程序何时收到一个客户连接请求或收到一个信号。所以程序要循环等待并处理事件,这就是事件循环。在事件循环中,等待事件一般使用I/O复用技术实现。在linux系统上一般是select、poll、epol_waitl等系统调用,用来等待一个或多个事件的发生。I/O框架库一般将各种I/O复用系统调用封装成统一的接口,称为事件多路分离器。调用者会被阻塞,直到分离器分离的描述符集上有事件发生。
  • 事件处理器(event handler):I/O框架库提供的事件处理器通常是由一个或多个模板函数组成的接口。这些模板函数描述了和应用程序相关的对某个事件的操作,用户需要继承它来实现自己的事件处理器,即具体事件处理器。因此,事件处理器中的回调函数一般声明为虚函数,以支持用户拓展。
  • 具体的事件处理器(concrete event handler):是事件处理器接口的实现。它实现了应用程序提供的某个服务。每个具体的事件处理器总和一个描述符相关。它使用描述符来识别事件、识别应用程序提供的服务。
  • Reactor 管理器(reactor)定义了一些接口,用于应用程序控制事件调度,以及应用程序注册、删除事件处理器和相关的描述符。它是事件处理器的调度核心。 Reactor管理器使用同步事件分离器来等待事件的发生。一旦事件发生,Reactor管理器先是分离每个事件,然后调度事件处理器,最后调用相关的模 板函数来处理这个事件。
模式演进
  • 单线程模式

这是最简单的单Reactor单线程模型。Reactor线程是个多面手,负责多路分离套接字,Accept新连接,并分派请求到处理器链中。该模型适用于处理器链中业务处理组件能快速完成的场景。不过这种单线程模型不能充分利用多核资源,所以实际使用的不多。
    

  • 多线程单Reactor模式

该模型在事件处理器(Handler)链部分采用了多线程(线程池),也是后端程序常用的模型。

  •  多线程多Reactor模式

比起第二种模型,它是将Reactor分成两部分,mainReactor负责监听并accept新连接,然后将建立的socket通过多路复用器(Acceptor)分派给subReactor。subReactor负责多路分离已连接的socket,读写网络数据;业务处理功能,其交给worker线程池完成。通常,subReactor个数上可与CPU个数等同。

优点

1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的
       2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销
       3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源
       4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性

缺点

1)相比传统的简单模型,Reactor增加了一定的复杂性,因而有一定的门槛,并且不易于调试。
      2)Reactor模式需要底层的Synchronous Event
Demultiplexer支持,比如Java中的Selector支持,操作系统的select系统调用支持,如果要自己实现Synchronous
Event Demultiplexer可能不会有那么高效。
      3)Reactor模式在IO读写数据时还是在同一个线程中实现的,即使使用多个Reactor机制的情况下,那些共享一个Reactor的Channel如果出现一个长时间的数据读写,会影响这个Reactor中其他Channel的相应时间,比如在大文件传输时,IO操作就会影响其他Client的相应时间,因而对这种操作,使用传统的Thread-Per-Connection或许是一个更好的选择,或则此时使用Proactor模式

最新文章

  1. C#知识体系(一) --- 常用的LInq 与lambda表达式
  2. 【转】Linux中xargs的用法
  3. Hive 的分桶 & Parquet 概念
  4. 基于隐马尔科夫模型(HMM)的地图匹配(Map-Matching)算法
  5. cxGrid 速度
  6. 【转】PHP框架性能测试报告 - ThinkPHP 3.2.3 Laravel 5.2 Yii2.0.5
  7. ubuntu10.04编译内核不显示grub菜单解决
  8. [转]笔记本Ubuntu系统关闭独显+省电降温设置
  9. C++ BigInteger 大整数类模板(转)
  10. asp.net URL DES加密 什在URL中的使用
  11. Principle-初步认识(简介)
  12. VS2015 搭建 Asp.net core 开发环境
  13. Windows下禁用锁屏热键WinKey+L
  14. 浅谈KMP算法
  15. 基于 Java Web 的毕业设计选题管理平台--系统设计和任务分配
  16. 【java】详解JFrame结构的分层
  17. asp.net页面中实现如果图片不存在则显示默认图片
  18. Windows Azure 应用程序短暂性故障处理
  19. 【CodeVS 2845】排序的代价
  20. ES6 Babel 简单使用

热门文章

  1. 使用 HttpWebRequest 类做 POST 请求没有应反
  2. 根父类:Object 类
  3. ThinkPHP5中如何实现模板完全静态化
  4. Sql Server设置用户只能查看并访问特定数据库
  5. java实现快速排序,归并排序
  6. 数据科学:pd.DataFrame.drop()
  7. jwt揭秘(含源码示例)
  8. Nginx Location指令URI匹配规则详解
  9. (05节)快速搭建SSM项目
  10. pandas的行列显示不全的解决方法