reactor的原理与实现

网络模型

  • 前情回顾
  • 服务器模型 Reactor和 Proactor
    • Reactor模型
    • Proactor模型
    • 同步I/O模拟Poractor模型
    • Libevent,libev,libuv
      • 优先级
      • 事件循环
      • 线程安全

前情回顾

网络IO,会涉及到两个系统对象:
  一个是用户空间调用的进程或线程
  一个是内核空间的内核系统
如果发生IO操作read时,会奖励两个阶段:
  1. 等待数据准备就绪
  2. 将数据从内核拷贝到进程或线程中
因为在以上两个阶段会有不同的情况发生,所以就出现了多种网络IO模型

服务器模型 Reactor和 Proactor

  对高并发编程,网络连接上的消息处理,可以分为两个阶段:等待消息准备好、消息处理。当使用默认的阻塞套接字时(例如上面提到的 1 个线程捆绑处理 1 个连接),往往是把这两个阶段合而为一,这样操作套接字的代码所在的线程就得睡眠来等待消息准备好,这导致了高并发下线程会频繁的睡眠、唤醒,从而影响了 CPU 的使用效率

  高并发编程方法当然就是把两个阶段分开处理。即,等待消息准备好的代码段,与处理消息的代码段是分离的。当然,这也要求套接字必须是非阻塞的,否则,处理消息的代码段很容易导致条件不满足时,所在线程又进入了睡眠等待阶段。

  Q: 那么问题来了,等待消息准备好这个阶段怎么实现?它毕竟还是等待,这意味着线程还是要睡眠的!
  A: 解决办法就是,线程主动查询,或者让 1 个线程为所有连接而等待!这就是 IO 多路复用了。多路复用就是处理等待消息准备好这件事的,它可以同时处理多个连接!它也可能“等待”,所以它也会导致线程睡眠,然而这不要紧,因为它一对多、可以监控所有连接。这样,当线程被唤醒执行时,就一定是有一些连接准备好被我们的代码执行了

作为一个高性能服务器程序通常需要考虑处理三类事件: I/O 事件,定时事件、信号。两种高效的事件处理模型:Reactor 和 Proactor

Reactor模型

  首先来回想一下普通函数调用的机制:程序调用某函数,函数执行,程序等待,函数将结果和控制权返回给程序,程序继续处理。
  Reactor 释义“反应堆”,是一种事件驱动机制。和普通函数调用的不同之处在于:应用程序不是主动的调用某个 API 完成处理,而是恰恰相反,Reactor 逆置了事件处理流程,应用程序需要提供相应的接口并注册到 Reactor 上,如果相应的事件发生,Reactor 将主动调用应用程序注册的接口,这些接口又称为“回调函数”
在这里插入图片描述
  Reactor 模式是处理并发 I/O 比较常见的一种模式,用于同步 I/O,中心思想是将所有要处理的 I/O 事件注册到一个中心 I/O 多路复用器上,同时主线程/进程阻塞在多路复用器上;一旦有 I/O 事件到来或是准备就绪(文件描述符或 socket 可读、写),多路复用器返回并将事先注册的相应 I/O 事件分发到对应的处理器中。

Reactor 模型有三个重要的组件:

  • 多路复用器:由操作系统提供,在 linux 上一般是 select, poll, epoll 等系-统调用。
  • 事件分发器:将多路复用器中返回的就绪事件分到对应的处理函数中。
  • 事件处理器:负责处理特定事件的处理函数。
    在这里插入图片描述
    具体流程如下:
      1. 注册读就绪事件和相应的事件处理器;
      2. 事件分离器等待事件;
      3. 事件到来,激活事件分发器,事件分发器调用事件对应的处理器;
      4. 事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。

Reactor 模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:

  • 响应快,不必为单个同步时间所阻塞,虽然 Reactor 本身依然是同步的;
  • 编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进
    程的切换开销;
  • 可扩展性,可以方便的通过增加 Reactor 实例个数来充分利用 CPU 资源;
  • 可复用性,reactor 框架本身与具体事件处理逻辑无关,具有很高的复用性;

  Reactor 模型开发效率上比起直接使用 IO 复用要高,它通常是单线程的,设计目标是希望单线程使用一颗 CPU 的全部资源,但也有附带优点,即每个事件处理中很多时候可以不考虑共享资源的互斥访问。可是缺点也是明显的,现在的硬件发展,已经不再遵循摩尔定
律,CPU 的频率受制于材料的限制不再有大的提升,而改为是从核数的增加上提升能力,当程序需要使用多核资源时,Reactor 模型就会悲剧,。
  为什么使用多核资源时,Reactor会悲剧呢?如果程序业务很简单,例如只是简单的访问一些提供了并发访问的服务,就可以直接开启多个反应堆,每个反应堆对应一颗 CPU 核心,这些反应堆上跑的请求互不相关,这是完全可以利用多核的。例如 Nginx 这样的 http 静态服务器。

Proactor模型

在这里插入图片描述
在这里插入图片描述
具体流程如下:

  1. 处理器发起异步操作,并关注 I/O 完成事件
  2. 事件分离器等待操作完成事件
  3. 分离器等待过程中,内核并行执行实际的 I/O 操作,并将结果数据存入用户自定义缓冲
    区,最后通知事件分离器读操作完成
  4. I/O 完成后,通过事件分发器呼唤处理器
  5. 事件处理器处理用户自定义缓冲区中的数据

  从上面的处理流程,我们可以发现 proactor 模型最大的特点就是 Proactor 最大的特点是:使用异步 I/O。所有的 I/O 操作都交由系统提供的异步 I/O 接口去执行。工作线程仅仅负责业务逻辑
  在 Proactor 中,用户函数启动一个异步的文件操作。同时将这个操作注册到多路复用器上。多路复用器并不关心文件是否可读或可写而是关心这个异步读操作是否完成异步操作是操作系统完成,用户程序不需要关心。多路复用器等待直到有完成通知到来。当操作系统完成了读文件操作——将读到的数据复制到了用户先前提供的缓冲区之后,通知多路复用器相关操作已完成。多路复用器再调用相应的处理程序,处理数据。
  Proactor 增加了编程的复杂度,但给工作线程带来了更高的效率。Proactor 可以在系统态将读写优化,利用 I/O 并行能力,提供一个高性能单线程模型。在 windows 上,由于没有 epoll 这样的机制,因此提供了 IOCP 来支持高并发, 由于操作系统做了较好的优化,windows 较常采用 Proactor 的模型利用完成端口来实现服务器
  在 linux 上,在2.6 内核出现了 aio 接口,但 aio 实际效果并不理想,它的出现,主要是解决 poll 性能不佳的问题,但实际上经过测试,epoll 的性能高于 poll+aio,并且 aio 不能处理 accept,
因此 linux 主要还是以 Reactor 模型为主。在不使用操作系统提供的异步 I/O 接口的情况下,还可以使用 Reactor 来模拟 Proactor,差别是:使用异步接口可以利用系统提供的读写并行能力,而在模拟的情况下,这需要在用户态实现。具体的做法只需要这样:

  1. 注册读事件(同时再提供一段缓冲区)
  2. 事件分离器等待可读事件
  3. 事件到来,激活分离器,分离器(立即读数据,写缓冲区)调用事件处理器
  4. 事件处理器处理数据,删除事件(需要再用异步接口注册)
    我们知道,Boost.asio 库采用的即为 Proactor 模型。不过 Boost.asio 库在 Linux 平台采用
    epoll 实现的 Reactor 来模拟 Proactor,并且另外开了一个线程来完成读写调度。

同步I/O模拟Poractor模型

在这里插入图片描述

  1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件。
  2. 主线程调用 epoll_wait 等待 socket 上有数据可读。
  3. 当 socket 上有数据可读时,epoll_wait 通知主线程。主线程从 socket 循环读取数据,
    直到没有更多数据可读,然后将读取到的数据封装成一个请求对象并插入请求队列。
  4. 睡眠在请求队列上的某个工作线程被唤醒,它获得请求对象并处理客户请求,然后
    往 epoll 内核事件表中注册 socket 上的写就绪事件。
  5. 主线程调用 epoll_wait 等待 socket 可写。
  6. 当 socket 可写时,epoll_wait 通知主线程。主线程往 socket 上写入服务器处理客户
    请求的结果。

  两个模式的相同点,都是对某个 IO 事件的事件通知(即告诉某个模块,这个 IO 操作可以进行或已经完成)。在结构上两者也有相同点:demultiplexor 负责提交 IO 操作(异步)、查询设备是否可操作(同步),然后当条件满足时,就回调注册处理函数。
  不同点在于,异步情况下(Proactor),当回调注册的处理函数时,表示 IO 操作已经完成;同步情况下(Reactor),回调注册的处理函数时,表示 IO 设备可以进行某个操作(can read or can write),注册的处理函数这个时候开始提交操作。

Libevent,libev,libuv

  libevent :名气最大,应用最广泛,历史悠久的跨平台事件库;
  libev :较 libevent 而言,设计更简练,性能更好,但对 Windows 支持不够好;
  libuv :开发 node 的过程中需要一个跨平台的事件库,他们首选了 libev,但又要支持Windows,故重新封装了一套,linux 下用 libev 实现,Windows 下用 IOCP 实现;

优先级

  libevent: 激活的事件组织在优先级队列中,各类事件默认的优先级是相同的,可以通过设置事件的优先级使其优先被处理
  libev: 也是通过优先级队列来管理激活的时间,也可以设置事件优先级
  libuv: 没有优先级概念,按照固定的顺序访问各类事件

事件循环

  libevent: event_base 用于管理事件
  libev: 激活的事件组织在优先级队列中,各类事件默认的优先级是相同的,
  libuv: 可以通 过设置事件的优先级 使其优先被处理

线程安全

  event_base 和 loop 都不是线程安全的,一个 event_base 或 loop 实例只能在用户的一个线程内访问(一般是主线程),注册到 event_base 或者 loop 的 event 都是串行访问的,即每个执行过程中,会按照优先级顺序访问已经激活的事件,执行其回调函数。所以在仅使用一个event_base 或 loop 的情况下,回调函数的执行不存在并行关系。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业计算机服务器中了babyk勒索病毒怎么办,babyk勒索病毒解密数据恢复

在数字化的今天,网络安全威胁不断增加,给企业的生产生活带来了严重影响,使得企业不得不重视数据安全问题。近日,云天数据恢复中心接到企业求助,企业的计算机服务器中了babyk勒索病毒,导致企业所有计算机系统…

【开源】基于Vue+SpringBoot的贫困地区人口信息管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 人口信息管理模块2.2 精准扶贫管理模块2.3 特殊群体管理模块2.4 案件信息管理模块2.5 物资补助模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 人口表3.2.2 扶贫表3.2.3 特殊群体表3.2.4 案件表3.2.5 物资补助表 四…

CleanMyMac X2024解锁完整官方版本

作为一款知名的系统清理软件,深受广大用户们的喜爱。它操作简洁,能够实现一键清理,包括但不仅限于清理语言文件、缓存文件、日志文件以及ISO图片缓存等。同时对于用户们比较头疼的iTunes垃圾,也能做到真正地清洁,不留文…

Hadoop(2):常见的MapReduce[在Ubuntu中运行!]

1 以词频统计为例子介绍 mapreduce怎么写出来的 弄清楚MapReduce的各个过程&#xff1a; 将文件输入后&#xff0c;返回的<k1,v1>代表的含义是&#xff1a;k1表示偏移量&#xff0c;即v1的第一个字母在文件中的索引&#xff08;从0开始数的&#xff09;&#xff1b;v1表…

学习在UE中通过Omniverse实现对USD文件的Live-Sync(实时同步编辑)

目标 前一篇 学习了Omniverse的一些基础概念。本篇在了解这些概念的基础上&#xff0c;我想体验下Omniverse的一些具体的能力&#xff0c;特别是 Live-Sync (实时同步) 相关的能力。 本篇实践了使用Omniverse的力量在UE中建立USD文件的 Live-Sync 编辑。由于相关的知识我是从…

Settings中电池选项-Android13

Settings中电池选项-Android13 1、设置中界面2、电池计算2.1 充电时间计算2.1.1 BatteryUsageStats获取2.1.2 BatteryStatsImpl计算 2.2 电池剩余使用时间2.2.1 Estimate获取2.2.2 BatteryStatsImpl计算 3、电池信息来源4、命令模拟* 日志 [电池]Android 9.0 电池未充电与充电字…

JVM介绍

程序计数器&#xff1a; 程序计数器属于线程的私有内存区域&#xff0c;记录当前线程的运行位置&#xff0c;以供多线程运行时上下文切换&#xff0c;字节码解释器通过程序计数器的增减来执行顺序分支循环等结构。独立于堆之外&#xff0c;因此程序计数器是唯一不会导致OutOfMe…

大数据深度解析NLP文本摘要技术:定义、应用与PyTorch实战

文章目录 大数据深度解析NLP文本摘要技术&#xff1a;定义、应用与PyTorch实战1. 概述1.1 什么是文本摘要&#xff1f;1.2 为什么需要文本摘要&#xff1f; 2. 发展历程2.1 早期技术2.2 统计方法的崛起2.3 深度学习的应用2.4 文本摘要的演变趋势 3. 主要任务3.1 单文档摘要3.2 …

SLAM算法与工程实践——SLAM基本库的安装与使用(6):g2o优化库(4)构建g2o的边

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

[原创][R语言]股票分析实战[4]:周级别涨幅趋势的相关性

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

Redis数据库入门学习(下载与安装、常用命令、在Java中操作Redis)

简介 下载与安装 数据类型 常用命令 1.字符串操作命令 2.哈希操作命令 3.列表操作命令 push是将元素总是插入到第一个 0表示第一个&#xff0c;1表示第二个。-1表示倒数第一个&#xff0c;-2表示倒数第二个。当前命令的意思是第一个到倒数第一个&#xff0c;即就是全部元素 rpo…

NUAA-云计算-考试

19级期末 问题 答案: md格式 自己想办法看 # 随堂测验#### 一、请简述GFS 的系统架构和特点。**1. 系统架构**- GFS将整个系统节点分为三类角色&#xff1a;- Client&#xff08;客户端&#xff09;&#xff1a;Client是GFS提供给应用程序的访问接口&#xff0c;以库文件的…

迪文屏开发保姆级教程5—表盘时钟和文本RTC显示

这篇文章要讲啥事呢&#xff1f; 本篇文章主要介绍了在DGBUS平台上使用表盘时钟和文本时钟RTC显示功能的方法。 文哥悄悄话&#xff1a; 官方开发指南PDF&#xff1a;&#xff08;不方便下载的私聊我发给你&#xff09; https://download.csdn.net/download/qq_21370051/8864…

【GitHub精选项目】抖音/ TikTok 视频下载:TikTokDownloader 操作指南

前言 本文为大家带来的是 JoeanAmier 开发的 TikTokDownloader 项目&#xff0c;这是一个高效的下载 抖音/ TikTok 视频的开源工具。特别适合用户们保存他们喜欢的视频或分享给其他人。 TikTokDownloader 是一个专门设计用于下载 TikTok 视频的工具&#xff0c;旨在为用户提供一…

OpenCV学习笔记 - 使用密集光流检测运动的简单方法

一、简述 使用光流进行运动检测的方法与帧间差分方法类似。主要区别在于第一步,我们将从光流而不是帧差分中获取初始运动信息(一些神经网络模型也是基于光流和原始图像进行运动识别训练的)。 该算法概述如下: 1、计算密集光流 2、获得运动掩模的阈值光流 3、在运动蒙版中查…

Adobe InDesign各版本安装指南

下载链接 https://pan.baidu.com/s/16uvK0ICpDVzacD5FEhUiyQ?pwd0531 ​ #2024版 1.鼠标右击【Indesign2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 Indesign2024(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击…

Real-Time Volumetric Cloudscapes

实时体积云景 GPU Pro 7 实时体积云景的翻译 4.1 概览 游戏中的实时体积云通常为了提高渲染效率而降低质量。最成功的方法仅限于低空蓬松半透明的层状云。我们提出了一种体积解决方案&#xff0c;可以使用不断变化并且逼真的结果填充天空&#xff0c;来描绘高海拔卷云和所有…

OpenAI开发者大会简介

文章目录 GPT-4 Turbo 昨天晚上 OpenAI的首届开发者大会召开 Sam Altman也做了公开演讲&#xff0c;应该说 这是继今年春天发布GPT-4之后 OpenAI在AI行业又创造的一个不眠夜 过去一年 ChatGPT绝对是整个科技领域最热的词汇 OpenAI 也依靠ChatGPT取得了惊人的成绩 ChatG…

​【C语言】乘法表

题目要求&#xff1a; 实现一个函数&#xff0c;打印乘法口诀表&#xff0c;口诀表的行数和列数自己指定 如&#xff1a;输入9&#xff0c;输出9 * 9口诀表&#xff0c;输出12&#xff0c;输出12 * 12的乘法口诀表。 题目分析&#xff1a; 我们观察乘法口诀表可以发现&#x…

【Kubernetes】控制器Statefulset

Statefulset控制器 一、概念二、Statefulset资源清单文件编写技巧2.1、查看定义Statefulset资源需要的字段2.2、查看statefulset.spec字段如何定义2.3、查看statefulset的spec.template字段如何定义 三、Statefulset使用案例&#xff1a;部署web站点3.1、编写一个Statefulset资…