服务器程序事件处理模式:Reactor和Proactor

Reactor

Reactor 翻译过来的意思是「反应堆」,这里的反应指的是「对事件反应」,也就是来了一个事件,Reactor 就有相对应的反应/响应。即 I/O 多路复用监听事件,收到事件后,根据事件类型分配(Dispatch)给某个进程 / 线程。

在每次感知到有事件发生(比如可读就绪事件)后,就需要应用进程主动调用 read 方法来完成数据的读取,也就是要应用进程主动将 socket 接收缓存中的数据读到应用进程内存中,这个过程是同步的,读取完数据后应用进程才能处理数据。

Reactor由两部分组成。在多线程环境下,可分为主线程和其余的工作线程。其中主线程负责监听文件描述符上的事件,包括连接事件和读写事件;而工作线程负责处理具体业务逻辑,包括读写数据和处理用户请求等。主线程可以有一个或多个。这种模式的工作流程如下图所示。

 Proactor

Reactor 是非阻塞同步网络模式,而 Proactor 是异步网络模式。Proactor 正是采用了异步 I/O 技术,所以被称为异步网络模型。主线程和内核负责处理所有IO事件,工作线程仅仅负责处理业务逻辑。在发起异步读写请求时,需要传入数据缓冲区的地址(用来存放结果数据)等信息,这样系统内核才可以自动帮我们把数据的读写工作完成,这里的读写工作全程由操作系统来做,并不需要像 Reactor 那样还需要应用进程主动发起 read/write 来读写数据,操作系统完成读写工作后,就会通知应用进程直接处理数据。Proactor模式工作流程如下。

 可惜的是,在 Linux 下的异步 I/O 是不完善的。aio 系列函数是由 POSIX 定义的异步操作接口,不是真正的操作系统级别支持的,而是在用户空间模拟出来的异步,并且仅仅支持基于本地文件的 aio 异步操作,网络编程中的 socket 是不支持的,这也使得基于 Linux 的高性能网络程序都是使用 Reactor 方案。

总结一下,Reactor 可以理解为“来了事件操作系统通知应用进程,让应用进程来处理”,而 Proactor 可以理解为“来了事件操作系统来处理,处理完再通知应用进程”。这里的“事件”就是有新连接、有数据可读、有数据可写的这些 I/O 事件;这里的“处理”包含从驱动读取到内核以及从内核读取到用户空间。

同步IO模拟Proactor

既然Linux 下的异步 I/O 不完善,那么可以使用同步Io方式模拟出Proactor模式。其原理是:主线程执行数据读写操作,读写完成之后,主线程向工作线程通知这一“完成事件”。 那么从工作线程的角度来看,它们就直接获得了数据读写的结果,接下来要做的只是对读写的结果进行逻辑处理。使用同步IO模型模拟出的Proactor模式的工作流程如下:

 并发编程的目的是让程序“同时”执行多个任务。如果程序是计算密集型的,并发编程会由于任务的切换使效率降低。但如果程序是IO密集型的,比如经常读写文件,访问数据库等,则由于IO操作的速度远没有CPU的计算速度快,所以让程序阻塞于IO操作将浪费大量的CPU时间。如果程序有多个执行线程,则当前被IO操作所阻塞的执行线程可主动放弃CPU (或由操作系统来调度),并将执行权转移到其他线程。这样一来,CPU就可以用来做更加有意义的事(除非所有线程都同时被IO操作所阻塞),而不是等待IO操作完成,因此CPU的利用率显著提升。需要根据不同情况选择所使用的事件模式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值