Reactor模式和Proactor模式

2019-05-17  本文已影响0人  浪白条

随着IO多路复用技术的出现,出现了很多事件处理模式。同步I/O模型通常由Reactor模式实现,而异步I/O模型则由Proactor模式实现。

image

Reator类图如上所示,Reactor模式又叫反应器或反应堆,即实现注册描述符(Handle)及事件的处理器(EventHandler),当有事件发生的时候,事件多路分发器(Event Demultiplexer)做出反应,调用事件具体的处理函数(ConcreteEventHandler::handle_event())。

Reator模式的典型启动过程如下:

  1. 创建Reactor
  2. 注册事件处理器(Reactor::register_handler())
  3. 调用事件多路分发器进入无限事件循环(Reacor:handle_events)
  4. 当操作系统通知某描述符状态就绪时,事件多路分发器找出并调用此描述符注册的事件处理器。

Reactor模式已经被广泛使用,著名的开源事件库libevent、libev、libuv都是使用Reactor模式。

Reactor模式的优点:

Reactor模式的缺点:

Reactor处理耗时长的操作(如文件I/O)会造成事件分发的阻塞,影响到后续事件的处理。

因此涉及到文件I/O相关的操作,需要使用异步I/O,即使用Proactor模式效果更佳。

image

Proactor模式的类图如上图所示,Proactor模式又叫前摄器或主动器模式。它用于实现异步I/O模型,运行流程如下:

1. Initiator主动调用Asynchronous Operation Processor发起异步I/O操作,

2. 记录异步操作的参数和函数地址放入完成事件队列(Completion Event Queue)中

3. Proactor循环检测异步事件是否完成。如果完成则从完成事件队列中取出回调函数完成回调。

Boost库中的asio就使用了Proactor模式,其底层的异步I/O由操作系统提供,而异步事件的分发还是由epoll/kequeue/select等实现。

两者区别

综上我们可以发现Reactor模式和Proactor模式的主要区别:

1. Reactor实现同步I/O多路分发,Proactor实现异步I/O分发。

如果只是处理网络I/O单线程的Reactor尚可处理,但如果涉及到文件I/O,单线程的Reactor可能被文件I/O阻塞而导致其他事件无法被分发。所以涉及到文件I/O最好还是使用Proactor模式,或者用多线程模拟实现异步I/O的方式。

2. Reactor模式注册的是文件描述符的就绪事件,而Proactor模式注册的是完成事件。

即Reactor模式有事件发生的时候要判断是读事件还是写事件,然后用再调用系统调用(read/write等)将数据从内核中拷贝到用户数据区继续其他业务处理。

而Proactor模式一般使用的是操作系统的异步I/O接口,发起异步调用(用户提供数据缓冲区)之后操作系统将在内核态完成I/O并拷贝数据到用户提供的缓冲区中,完成事件到达之后,用户只需要实现自己后续的业务处理即可。

3. 主动和被动

Reactor模式是一种被动的处理,即有事件发生时被动处理。而Proator模式则是主动发起异步调用,然后循环检测完成事件。

最后我们知道linux系统提供的异步I/O,只支持O_DIRECT,不能带缓存。因此出现了开源库libeio,它和Linux的异步I/O一样也是用多线程模拟,但是更高效。下图是libeio的异步I/O实现,是不是很像Proactor模式啊。

image

https://www.cnblogs.com/bitkevin/p/5724410.html

上一篇下一篇

猜你喜欢

热点阅读