【I/O】基于事件驱动的 I/O 模型---Reactor

Reactor 模型

BIO 到 I/O 多路复用

为每个连接都创建一个线程

假设我们现在有一个服务器,想要对接多个客户端,那么最简单的方法就是服务端为每个连接都创建一个线程,处理完业务逻辑后,随着连接关闭线程也要销毁,但是这样线程创建和销毁,不仅会带来性能开销也会带来资源浪费,如果同时有几万个连接,创建几万个线程是不现实的。

使用线程池优化

我们很容易想到使用线程池来优化,也就是不再为每个连接都创建一个线程,而是创建一个「线程池」,将连接分配给线程,然后一个线程可以处理多个连接业务,不过这样的话又会有一个新的问题,当一个连接对应一个线程的时候,线程的处理流程一般是 read -> 业务处理 -> send,当没有数据可读的时候,线程会阻塞在 read 上,所以我们在使用线程池的时候,如果某个线程阻塞在了 read 上,它是没有办法继续处理其他连接的业务。

要解决这一问题,我们需要将连接改为「非阻塞」的,然后线程不断轮询调用 read 操作来查看是否有数据可读,但是轮询也是需要消耗 CPU 的,同时一个线程管理的连接越多轮询的消耗也就越大。

I/O 多路复用

线程池带来的问题在于,线程不知道当前连接是否有数据可读,因此需要不断的轮询进行 read 操作去检测哪个连接有数据可读。I/O 多路复用可以很好的解决这一问题,I/O 多路复用使得只有当连接上有数据的时候,才去发起 read 操作,I/O 多路复用会用一个系统调用函数(select() poll() epoll() )来监听我们所关心的连接,通过系统调用可以从内核中获取多个事件。

在获取事件时,先把我们关心的连接发送个内核,在有内核进行检测:

  • 如果没有事件发生,线程只需要阻塞这个系统调用,而无需像前面的线程池方案那样轮询调用 read 操作
  • 如果有事件发生,内核会返回产生了事件的连接,线程就会从阻塞状态返回,然后在用户态再处理这些连接的业务即可

Reactor 模型

Reactor 模型: I/O 多路复用监听事件,收到事件后,根据事件类型分配给某个线程

Reactor 主要由 Reactor 和 处理资源池 两个核心部分组成:

  • Reactor 负责监听和分发事件,事件包括连接事件、读写事件
  • 处理资源池负责处理事件,如 read -> 业务处理 -> send

单 Reactor 单线程

三个对象 Reactor、Acceptor、Handler

  • Reactor 对象的作用是监听和分发事件
  • Acceptor 对象的作用是获取连接
  • Handler 对象的作用是处理业务

在这里插入图片描述

select、accept、read、send 是系统调用函数,dispatch 是事件分发操作

流程:

  • Reactor 对象通过 select 监听事件,收到事件后通过 dispatch 进行分发
  • 如果事件是建立连接的事件,则交由 Acceptor 对象进行处理,Acceptor 对象会通过 accept 方法获取连接,并将连接注册到 select 上,然后创建一个 Handler 对象来处理后续的响应事件
  • 如果不是连接创建事件,则交由对应的 Handler 对象来进行处理
  • Handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程

单 Reactor 单线程方案,所有的工作都在一个线程上完成,实现简单,但有两个缺点:

  • 只有一个线程,无法利用多核 CPU 的优势
  • Handler 对象在业务处理时,整个线程无法处理其他连接的事件,如果业务耗时比较长的话,会出现响应延迟

单 Reactor 多线程

在这里插入图片描述

流程:

  • Reactor 对象通过 select 监听事件,收到事件后通过 dispatch 分发事件
  • 如果是连接事件,则将其分发给 Acceptor 对象进行处理,Acceptor 对象通过 accept 方法获取连接,并将连接注册到 select ,然后创建一个 Handler 对象来处理后续的响应事件
  • 如果不是创建连接事件,则交由对应的 Handler 对象进行处理
  • Handler 对象不再进行业务处理,只负责数据的接收和发送,Handler 对象通过 read 方法读取连接中的数据后,会将数据发送给子线程里的 Processor 对象进行业务处理
  • 子线程的 Processor 对象就进行业务处理,业务处理完成后,将结果发送给主线程中的 Handler 对象,接着由 Handler 对象负责将结果使用send方法发送给客户端

单 Reactor 多线程方案能够充分利用多核 CPU 的能力,但是即使业务处理是采用线程池多线程的进行,但是最后还是要靠主线程的 Handler 进行发送,这就带来了 多线程共享数据竞争 的问题,要避免这个问题就不得不在访问共享数据是加上互斥锁,来保证在任一时间内只有一个线程访问共享数据。

单 Reactor 单线程方案还有一个问题,一个 Reactor 担任事件的监听和分发任务,而且是在主线程中进行的,在面对瞬时间的高并发场景,很容易成为性能的瓶颈

多 Reactor 多线程

在这里插入图片描述

流程:

  • 主线程的 MainReactor 通过 select 只监听建立连接事件,收到事件后交给 Acceptor 对象,Acceptor 对象通过 accept 获取连接,随后 MainReactor 将新的连接分配给某个子线程
  • 子线程的 SubReactor 对象将主线程分配的连接注册到 select 上继续进行监听,并创建一个 Handler 对象进行后续连接的响应事件
  • 如果有新的事件发生,SubReactor 会调用对应连接的 Handler 进行事件响应
  • Handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程

优点:

  • 主线程和子线程分工明确,主线程只负责接收新连接,子线程负责负责监听连接的读写事件以及后续的业务处理
  • 主线程和子线程的交互也很简单,主线程只需要把新的连接传递给子线程,子线程无需返回数据,直接可以在子线程中完成数据的处理和发送给客户端

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/308834.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…

Java编程练习之抽象类与抽象方法

使用抽象类和抽象方法时&#xff0c;需要遵循以下原则&#xff1a; 1&#xff09;在抽象类中&#xff0c;可以包含抽象方法&#xff0c;也可以不包含抽象方法&#xff0c;但是包含了抽象方法的类必须被定义为抽象类&#xff1b; 2&#xff09;抽象类不能直接被实例化&#xf…

BugKu:Flask_FileUpload

Flask_FileUpload 解题思路 查看源码&#xff1a; 编写上传的文件 获得结果 小结 文件上传漏洞&#xff1a; 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的&#xff0c;“文件上…

探索ERC20代币:构建您的第一个去中心化应用

下面文章中会涉及到该资源中的代码&#xff0c;如果想要完整版代码可以私信我获取&#x1f339; 文章目录 概要整体架构流程技术名词解释ERC20智能合约web3.js 技术细节ERC20合约部署创建前端界面前端与智能合约互连运行DAPP 小结 概要 在加密货币世界中&#xff0c;ERC20代币…

poi-tl的使用(通俗易懂,全面,内含动态表格实现 包会!!)

最近在做项目时候有一个关于解析Html文件&#xff0c;然后将解析的数据转化成word的需求&#xff0c;经过调研&#xff0c;使用poi-tl来实现这个需求&#xff0c;自己学习花费了一些时间&#xff0c;现在将这期间的经验总结起来&#xff0c;让大家可以快速入门 poi-tl的介绍 …

大数据产品有哪些分类?各类里知名大数据产品都有哪些?

随着互联网技术的持续进步和全球数字化转型的推进&#xff0c;我们正处于一个数据爆炸的时代。在这样的大背景下&#xff0c;大数据已经逐渐崭露头角&#xff0c;成为了推动各行各业发展的关键因素和核心资源。大数据不仅仅是指数据的规模巨大&#xff0c;更重要的是它蕴含的价…

Python八股文:基础知识Part2

1. Python中变量的保存和访问 Python中的变量实际上是一个指向对象的引用&#xff0c;每个对象都有一个唯一的标识符&#xff08;即内存地址&#xff09;。对于一些不可变对象&#xff0c;如字符串和整数&#xff0c;因为它们的值不可更改&#xff0c;所以当多个变量引用相同的…

彩虹聚合DNS管理系统源码

聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&#xff0c;每个用户可分配不同的域名解析权限&#xff1b;支持API接口&#xff0c;支持获取域名…

建造者模式:构造复杂对象的艺术

在面向对象的设计中&#xff0c;建造者模式是一种重要的创建型设计模式&#xff0c;专门用来构建复杂的对象。它主要目的是将对象的构造代码与其表示代码分离&#xff0c;使同样的构建过程可以创建不同的表示。本文将详细介绍建造者模式的定义、实现、应用场景以及优缺点&#…

虚拟货币:数字金融时代的新工具

在数字化时代的到来之后&#xff0c;虚拟货币逐渐成为了一种广为人知的金融工具。虚拟货币是一种数字化的资产&#xff0c;它不像传统货币那样由政府或中央银行发行和监管。相反&#xff0c;虚拟货币通过密码学技术和分布式账本技术来实现去中心化的发行和交易。 虚拟货币的代…

内网通如何去除广告,内网通免广告生成器

公司使用内网通内部传输确实方便&#xff01;但是会有广告弹窗推送&#xff01;这个很烦恼&#xff01;那么如何去除广告呢&#xff01; 下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1CVVdWexliF3tBaFgN1W9aw?pwdhk7m 提取码&#xff1a;hk7m ID&#xff1a;…

如何进行宏观经济预测

理性预期经济学提出了理性预期的概念&#xff0c;强调政府在制定各种宏观经济政策时&#xff0c;要考虑到各行为主体预期对政策实施有效性的影响&#xff0c;积极促成公众理性预期的形成&#xff0c;从而更好地实现宏观调控的目标。政府统计要深入开展统计分析预测研究&#xf…

享元模式:优化资源利用的高效策略

在面向对象的软件开发中&#xff0c;享元模式是一种结构型设计模式&#xff0c;旨在减少内存使用&#xff0c;通过共享尽可能多的相似对象来提高应用程序的效率。本文将详细介绍享元模式的定义、实现、应用场景以及优缺点。 1. 享元模式的定义 享元模式&#xff08;Flyweigh…

免费的 ChatGPT 网站(六个)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、insCode二、讯飞星火三、豆包四、文心一言五、通义千问六、360智脑 现在智能…

PoE 技术

1 PoE 技术产生背景 随着 WLAN 、 VoIP 、网络视频监控等新业务的飞速发展,大量的无线 LAN 访问点、 IP 电话、 IP 网络摄像头等基于 IP 的终端出现在工业现场。这些设备通常数量众多、位置特殊 、 布线复杂、设备取电困难,其实施部署不仅消耗大量人力物力,…

终端界面外观修改

终端界面外观修改 考虑到实验报告等内容截取命令行会出现不清晰现象 所以特意对cmd命令行的界面外观修改方便打印的时候清晰显示内容 流程 1.右键命令行窗口&#xff0c;点击属性 2.点击颜色 3.选择屏幕背景&#xff0c;窗口颜色选择白色 4.选择屏幕文字&#xff0c;点…

【计算机毕业设计】基于Java+SSM的实战开发项目150套(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f9e1;今天给大家分享150的Java毕业设计&#xff0c;基于ssm框架&#xff0c;这些项目都经过精心挑选&#xff0c;涵盖了不同的实战主题和用例&#xff0c;可做毕业设计和课程…

SpringCloudAlibaba-整合nacos(二)

目录地址&#xff1a; SpringCloudAlibaba整合-CSDN博客 一、nacos服务部分 1.下载nacos&#xff0c;并执行数据库脚本&#xff1a;nacos-mysql.sql 2.修改配置文件&#xff0c;配置mysql 3.启动nacos ./startup.sh -m standalone 4.访问&#xff1a;http://127.0.0.1:884…

pytest常用钩子函数

1、什么叫钩子函数 在Pytest框架中&#xff0c;钩子函数是一种允许用户扩展或者自定义测试执行过程的机制。钩子函数允许用户在测试的不同阶段插入自定义的代码&#xff0c;以实现特定的行为&#xff0c;操作或处理。这种插入式的机制使得Pytest具有高度的灵活性和扩展性。 如…