【Proactor模型】事件驱动模型 - Proactor模型简述

发布时间 2023-07-08 22:19:23作者: -zx-

Proactor模型

Reactor是非阻塞同步网络模式,而Proactor是异步网络模式。

阻塞I/O:当程序执行read,线程会被阻塞,一直等到内核数据准备好,并把数据从内核缓冲区拷贝到应用程序的缓冲区中,当拷贝过程完成,read才会返回。阻塞等待的是"内核数据准备好"和"数据从内核态拷贝到用户态"这两个过程。

img

非阻塞I/O:非阻塞I/O的read请求在数据未准备好的情况下立即返回,可以继续向下执行,此时应用程序不断轮询内核,直到数据准备好,内核将数据拷贝到应用程序缓冲区,read调用才回去到结果。

img

这里最后一次read调用,获取数据的过程,是一个同步的过程,是需要等待的过程。这里的同步是指从内核态的数据拷贝到用户程序的缓存区这个过程

socket不做任何设置的话,默认是阻塞I/O,当设置了O_NONBLOCK彪子,就表示使用的是非阻塞I/O的方式访问。

而无论read和send是阻塞I/O,还是非阻塞I/O,都是同步调用,因为在read调用时,内核将数据从内核空间拷贝到用户空间都是需要等待的,这个过程是同步的,如果内核实现的拷贝效率不高,read调用就会在这个同步过程中等待比较长的时间。

异步I/O:真正的异步I/O应该是内核数据准备好数据从内核态拷贝到用户态这两个过程都不用等待

当发起aio_read(异步I/O)之后,就立即返回,内核会自动从内核空间拷贝到用户空间,这个拷贝过程同样是异步的,内核自动完成的,和前面的同步操作不一样,应用程序不需要主动发起拷贝动作。

img

Proactor正是采用了异步I/O模型,所以被称为异步网络模型。

Proactor模型和Reactor模型的异同

  • Reactor是非阻塞同步网络模式,感知的是就绪可读写事件。在每次感知到有事件后,就需要应用进行主动调用read方法来完成数据的读取,也就是要应用进程主动将socket接收缓存中的数据读到应用进程内存中,这个过程是同步过程,读完数据后应用进程才能处理数据。

  • Proactor是异步网络模式,感知的是已完成的读写事件。再发起异步读写请求时,需要传入数据缓冲区的地址(用于存放结果数据)等信息,这样系统内核才可以自动把数据的读写工作完成,这里的读写工作全部由操作系统来做,并不需要像Reactor那样还需要应用进程主动发起read/write来读写数据,操作系统完成读写工作后,会通知应用进程直接处理数据。

Reactor模式可以理解为:来了事件操作系统通知应用进程,让应用进程来处理。

Proactor模式可以理解为:来了事件操作系统来处理,处理完再通知应用进程。

无论是Reactor,还是Proactor都是一种基于事件分发的网络编程模式,区别在于Reactor模式是基于待完成的I/O事件,而Proactor模式是基于已完成的I/O事件。

Proactor模式示意图:

img

Proactor模式的工作流程:

  • Proactor Initiator 负责创建 Proactor 和 Handler 对象,并将 Proactor 和 Handler 都通过 Asynchronous Operation Processor 注册到内核;
  • Asynchronous Operation Processor 负责处理注册请求,并处理 I/O 操作;
  • Asynchronous Operation Processor 完成 I/O 操作后通知 Proactor;
  • Proactor 根据不同的事件类型回调不同的 Handler 进行业务处理;
  • Handler 完成业务处理;

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

而 Windows 里实现了一套完整的支持 socket 的异步编程接口,这套接口就是 IOCP,是由操作系统级别实现的异步 I/O,真正意义上异步 I/O,因此在 Windows 里实现高性能网络程序可以使用效率更高的 Proactor 方案。

从效率角度, 而 Windows 里实现了一套完整的支持 socket 的异步编程接口,这套接口就是 IOCP,是由操作系统级别实现的异步 I/O,真正意义上异步 I/O,因此在 Windows 里实现高性能网络程序可以使用效率更高的 Proactor 方案。 不过,无论是 Reactor,还是 Proactor,都是一种基于「事件分发」的网络编程模式,区别在于 Reactor 模式是基于「待完成」的 I/O 事件,而 Proactor 模式则是基于「已完成」的 I/O 事件。












参考文章:

https://www.zhihu.com/question/26943938