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

时间:2022-09-09 14:37:38

  不同的操作系统实现的io策略可能不一样,即使是同一个操作系统也可能存在多重io策略,常见如linux上的select,poll,epoll,面对这么多不同类型的io接口,这里需要一层抽象api来完成,所以就演变出来两种高性能的io的设计模式,分别是Reactor(同步IO)和Proactor(异步IO)。

1. Reactor 

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

Reactor 的标准(典型)的工作方式是:

(1)应用程序注册读就绪事件和相关联的事件处理器

(2)Reactor阻塞等待内核事件通知

(3)Reactor收到通知,然后分发可读写事件(读写准备就绪)到用户事件处理函数

(4)用户读取数据,并处理数据

(5)事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。

2. Proactor

Proactor 的标准(典型)的工作方式是:

(1)应用程序初始化一个异步读取操作,然后注册相应的事件处理器,此时事件处理器不关注读取就绪事件,而是关注读取完成事件,这是区别于Reactor的关键。

(2)事件分离器等待读取操作完成事件

(3)在事件分离器等待读取操作完成的时候,操作系统调用内核线程完成读取操作,并将读取的内容放入用户传递过来的缓存区中。这也是区别于Reactor的一点,Proactor中,应用程序需要传递缓存区。

(4)事件分离器捕获到读取完成事件后,激活应用程序注册的事件处理器,事件处理器直接从缓存区读取数据,而不需要进行实际的读取操作。

3. 简单的理解(抄过来的)

并发系统常使用reactor模式,代替常用的多线程的处理方式,节省系统的资源,提高系统的吞吐量。

  以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐。就像一个网站会有很多的请求,要求服务器做一些事情。处理这些就餐事件的就需要我们的服务人员了。

(1) 在多线程处理的方式会是这样的:

一个人来就餐,一个服务员去服务,然后客人会看菜单,点菜。 服务员将菜单给后厨。

二个人来就餐,二个服务员去服务……

五个人来就餐,五个服务员去服务…

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

  (2) 在线程池处理的方式会是这样的:(固定的10个人去服务,但仍然供不应求)

  (3) Reactor设计模式: 单个线程来做多线程的事

   顾客通过呼叫服务员(event事件)通知服务员,菜单写好了,服务员就会把菜单交给厨师(事件处理器),厨师就会去做菜了。

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

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

  (4) Proactor设计模式: 让别人做完通知自己

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

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

 

4. 两者的区别

区别 Reactor Proactor
定义

被动的等待指示事件的到来,并作出反应

它有一个等待的过程,做什么事都要放入到监听事件集合中等待handler可用时再操作。

直接调用异步读写操作,调用完立即返回,

由内核负责写操作,写完后调用相应的回调函数处理后续逻辑。

实现

实现了一个被动的事件分离和分发模型

服务等待请求事件的到来,再通过不间断地同步处理事件做出反应。

实现了一个主动的事件分离和分发模型。

允许多个任务并发的执行,从而提高吞吐量,可执行耗时长的任务。

主动与被动 被动 主动
同步与异步 同步 异步
优点

1. 简单。实现相对简单,对于耗时短的处理场景处理高效。

2. 单线程。操作系统可在多个事件源上等待。避免了多线程编程相关的性能开销和编程复杂性。

3. 不用锁。事件的串行化对应用时透明的,可以顺序的同步执行而不需加锁。

4. 事务隔离。将与应用无关的   多路分解和分配机制 与应用相关的   回调函数  分离开来

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

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

1. 复杂。实现逻辑复杂。

2. 依赖OS对异步的支持(很少很难)

使用场景

同时接受多个服务请求,并且依次同步的处理他们的事件驱动程序。

耗时短的。

步接受和同时处理多个服务请求的事件驱动程序

耗时长的。

五.总结

基于事件驱动的网络编程的两种设计模式:

  Reactor (反应堆 同步IO)  java NIO  多路复用IO  redis libevent  Linux epoll

  Proactor(前摄器 异步IO)  java AIO  异步IO模型  目前只有 Windows IO completion port.(iocp)模型

  1. 只有IOCP是asynchronous I/O,其他机制或多或少都会有一点阻塞。
  2. select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善
  3. epoll, kqueue、select是Reacor模式,IOCP是Proactor模式。
  4. java nio包是select模型。
  5. epoll, kqueue、select 等是IO策略,他们属于设计模式,他们实现设计模式,相对于设计模式,设计策略更细节,设计模式更抽象。

摘录网址:

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

IO设计模式之Reactor和Proactor

reactor和proactor模式

Reactor模式,或者叫反应器模式