一、Proactor出现的背景:

前面我们介绍了 Reactor 网络模型(文章地址:https://blog.csdn.net/a745233700/article/details/122660246),知道了 Reactor 是非阻塞同步网络模型,而 Proactor 是异步网络模型。

(1)对于阻塞IO,当用户程序执行 read,线程会被阻塞,一直等内核数据准备好,并把数据从内核缓冲区拷贝到应用程序的缓冲区中,当拷贝过程完成,read 才会返回。如下图:

阻塞等待的是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程

(2)对于非阻塞IO,非阻塞的read请求在数据未准备好的情况下立即返回,可以继续往下执行,此时应用程序不断轮询内核,直到数据准备好,内核将数据拷贝到应用程序缓冲区,read 调用才可以获取到结果。过程如下图:

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

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

(3)对于异步IO,指的是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程都不用等待。当我们发起 aio_read (异步 I/O) 之后,就立即返回,内核自动将数据从内核空间拷贝到用户空间,这个拷贝过程同样是异步的,内核自动完成的,和前面的同步操作不一样,应用程序并不需要主动发起拷贝动作。过程如下图:

Proactor 正是使用了异步 I/O 技术,所以被称为异步网络模型。现在我们再来理解 Reactor 和 Proactor 的区别,就比较清晰了:

  • Reactor 是同步非阻塞网络模型,感知的是就绪可读写事件。在每次感知到有事件发生(比如可读就绪事件)后,就需要应用进程主动调用 read 方法来完成数据的读取,也就是要应用进程主动将 socket 接收缓存中的数据读到应用进程内存中,这个过程是同步的,读取完数据后应用进程才能处理数据。
  • Proactor 是异步网络模式, 感知的是已完成的读写事件。在发起异步读写请求时,需要传入数据缓冲区的地址(用来存放结果数据)等信息,这样系统内核才可以自动帮我们把数据的读写工作完成,这里的读写工作全程由操作系统来做,并不需要像 Reactor 那样还需要应用进程主动发起 read/write 来读写数据,操作系统完成读写工作后,就会通知应用进程直接处理数据。

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

举个实际生活中的例子,Reactor 模式就是快递员在楼下,给你打电话告诉你快递到你家小区了,你需要自己下楼来拿快递。而在 Proactor 模式下,快递员直接将快递送到你家门口,然后通知你。

从上面介绍的内容我们不难看出 Proactor 产生的主要原因:Reactor 性能确实非常高,适合高并发场景,但它依然存在一个问题,那就是它是同步IO。同步IO需要线程自己等待内核准备好数据,在内核准备数据的过程中,当前线程是阻塞的,这样就会导致如果某个线程因为读取IO的时间过长(比如读取文件、写文件),则它势必会影响其他线程的执行。

二、Proactor 的执行流程:

无论是 Reactor,还是 Proactor,都是一种基于「事件分发」的网络编程模式,区别在于 Reactor 模式是基于「待完成」的 I/O 事件,而 Proactor 模式则是基于「已完成」的 I/O 事件。接下来,一起看看 Proactor 模式的示意图:

介绍一下 Proactor 模式的工作流程:

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

需要注意的是:Proactor关注的不是就绪事件,而是完成事件,这是区分Reactor模式的关键点。

下面就简单介绍下 Proactor 模型处理读取操作的主要流程:

  • (1)应用程序初始化一个异步读取操作,然后注册相应的事件处理器,此时事件处理器不关注读取就绪事件,而是关注读取完成事件,这是区别于Reactor的关键。
  • (2)事件分离器等待读取操作完成事件
  • (3)在事件分离器等待读取操作完成的时候,操作系统调用内核线程完成读取操作,并将读取的内容放入用户传递过来的缓存区中。这也是区别于Reactor的一点,Proactor中,应用程序需要传递缓存区。
  • (4)事件分离器捕获到读取完成事件后,激活应用程序注册的事件处理器,事件处理器直接从缓存区读取数据,而不需要进行实际的读取操作。

异步IO都是操作系统负责将数据读写到应用传递进来的缓冲区供应用程序操作。

Proactor中写入操作和读取操作基本一致,只不过监听的事件是写入完成事件而已。

三、Proactor 的缺点:

Proactor 性能确实非常强大,效率也高,但是同样存在以下缺点:

(1)内存的使用:缓冲区在读或写操作的时间段内必须保持住,可能造成持续的不确定性,并且每个并发操作都要求有独立的缓存,相比Reactor模型,在Socket已经准备好读或写前,是不要求开辟缓存的;

(2)操作系统的支持:Windows 下通过一套完整的支持 socket 的异步编程接口,也就是通过 IOCP 实现了真正的异步,但 Linux 系统下的异步 IO 还不完善,aio 系列函数是由 POSIX 定义的异步操作接口,不是真正的操作系统级别支持的,而是在用户空间模拟出来的异步,并且仅仅支持基于本地文件的 aio 异步操作,网络编程中的 socket 是不支持的。因此,Linux 系统下高并发网络编程都是以 Reactor 模型为主

参考文章:

https://blog.csdn.net/qq_34827674/article/details/116175772

https://cloud.tencent.com/developer/article/1488120

Java IO篇:什么是 Proactor 网络模型?相关推荐

  1. Java IO篇 Java IO编程

    Java IO 一.java io 概述 1.1 相关概念 二.Java IO类库的框架 2.1 Java IO的类型 2.2 IO 类库 三.Java IO的基本用法 3.1 Java IO :字节 ...

  2. Java IO篇:什么是 Reactor 网络模型?

    一.什么是 Reactor 模型: The reactor design pattern is an event handling pattern for handling service reque ...

  3. Java IO篇:什么是零拷贝?

    在介绍零拷贝的IO模式之前,我们先简单了解下传统的IO模式是怎么样的? 一.传统的IO模式: 传统的IO模式,主要包括 read 和 write 过程: read:把数据从磁盘读取到内核缓冲区,再拷贝 ...

  4. Java IO篇:序列化与反序列化

    1.什么是序列化: 两个服务之间要传输一个数据对象,就需要将对象转换成二进制流,通过网络传输到对方服务,再转换成对象,供服务方法调用.这个编码和解码的过程称之为序列化和反序列化.所以序列化就是把 Ja ...

  5. 图学java基础篇之IO

    java io体系 如图可以看出,java的io按照包来划分的话可以分为三大块:io.nio.aio,但是从使用角度来看,这三块其实揉杂在一起的,下边我们先来概述下这三块: io:主要包含字符流和字节 ...

  6. cmd 将文件夹下文件剪切到另外一个文件_总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇...

    本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...

  7. java 文件 剪切_总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇

    本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 很多朋友在看我的<java IO总结系列>之前觉得创建文件.文件夹删除文件这些基础操作真的是太简单了.但看了我的文章之后,有小 ...

  8. java 中io的删除文件_总结删除文件或文件夹的7种方法-JAVA IO基础总结第4篇

    本文是Java IO总结系列篇的第4篇,前篇的访问地址如下: 如果您阅读完成,觉得此文对您有帮助,请给我点个赞,您的支持是我不竭的创作动力. 为了方便大家理解,我特意制作了本文对应的视频:总结删除文件 ...

  9. 菜鸟学习笔记:Java提升篇6(IO流2——数据类型处理流、打印流、随机流)

    菜鸟学习笔记:Java IO流2--其他流 字节数组输入输出流 数据类型处理流 基本数据类型 引用类型 打印流 System.in.System.out.System.err 随机流RandomAcc ...

最新文章

  1. getElementsByclassName
  2. 面向对象1(super、this)
  3. css 图片剪裁居中
  4. 我的世界服务器怎么修改书与笔,我的世界书与笔怎么做 我的世界书与笔怎么用...
  5. [vSphere培训实录]8G内存笔记本搭建vSphere测试环境
  6. Docker镜像、容器的理解和使用方法
  7. 微信公众号数据2019_如何制作微信公众号图文素材 微信公众号采集器好用吗
  8. 通过bin-log对mysql进行数据恢复
  9. 错误:[IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序 解决方法_QT
  10. report machine实现报表分栏
  11. 实验室信息管理系统的进化史
  12. 手机照片局部放大镜_怎样发照片才能惊艳朋友圈?
  13. 如何从根本上防止服务器被攻击
  14. 2023最新最新ChatGPT超全面从基础到实战视频教程/有兴趣自己学
  15. Caffeine Eviction策略
  16. USB3.0传输数据、解析处理和帧率计算
  17. Power BI——建模
  18. 照书写轮子——图的五种常见接口的实现(DFS、BFS、最小生成树问题、最短路径问题、关键路径问题)
  19. Python利用requests抓取页面源代码(基础)
  20. react源码中的fiber架构

热门文章

  1. 最新进展概述:澄清式提问辅助理解信息检索中的用户意图
  2. Github项目推荐 | OI Wiki:编程竞赛最全知识整合站点
  3. 当前最好的非深度迁移学习方法:流形空间下的分布对齐
  4. 超全总结:神经网络加速之量化模型 | 附带代码
  5. 深度学习在CTR预估中的应用 | CTR深度模型大盘点
  6. 蓝桥备赛第一周2021.1.11 递归 枚举 位运算
  7. PyTorch机器学习从入门到实践-CH1
  8. 【算法系列之万字总结常用的查找算法,持续补充更新中】
  9. springboot+springsecurity+mybatis plus之用户认证
  10. PaddleOCR——运行错误【Please compile with gpu to EnableGpu()】解决方案