网络IO模型以及实际应用

网络IO模型

本文主要介绍了几种不同的网络IO模型,以及实际应用中使用到的Reactor模型等。

我们常说的网络IO模型,主要包含阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO。在这里插入图片描述在这里插入图片描述

  • 根据第一个阶段:是否需要阻塞,分为阻塞和非阻塞IO。第二个阶段:将数据从内核copy到用户空间,分为同步和异步。这一步如果是操作系统自动完成,是异步。否则是同步。

BIO、NIO、AIO的区别

同步阻塞IO(BIO):用户进程发起一个IO操作以后,必须等待IO操作的真正完成后,才能继续运行;
同步非阻塞IO(NIO):用户进程发起一个IO操作以后,可做其它事情,但用户进程需要经常询问IO操作是否完成,这样造成不必要的CPU资源浪费。

异步非阻塞IO(AIO):用户进程发起一个IO操作然后,立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知。类比Future模式。

NIO相对于BIO来说一大进步。客户端和服务器之间通过Channel通信。NIO可以在Channel进行读写操作。这些Channel都会被注册在Selector多路复用器上。Selector通过一个线程不停的轮询这些Channel。找出已经准备就绪的Channel执行IO操作。 NIO 通过一个线程轮询,实现千万个客户端的请求,这就是非阻塞NIO的特点
异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理.
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
AIO 并没有采用NIO的多路复用器,而是使用异步通道的概念。其read,write方法的返回类型都是Future对象。而Future模型是异步的,其核心思想是:去主函数等待时间

IO多路复用

为什么要有这项技术?解决了什么问题?

同步非阻塞,针对每一个用户请求(读、写操作),单独创建一个线程去进行处理(读、写)。线程资源是珍贵和宝贵的。对每一个请求创建一个线程,不合理也非常浪费。因此出现了IO多路技术。
使用单线程处理多个IO操作。只有当其中某一个IO准备就绪后才会进行相应的处理,从而提高程序的效率和并发性。

I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的。
有以下几种实现方式:
在这里插入图片描述

异步IO(AIO)

应用进程通知内核开始一个异步I/O操作,并让内核在整个操作(包含将数据从内核复制到应该进程的缓冲区)完成后通知应用进程。实际中很少有应用。

Reactor模型和Proactor模型(实际应用)

无论是C++还是Java编写的网络框架,大多数都是基于Reactor模型进行设计和开发,Reactor模型基于事件驱动,特别适合处理海量的I/O事件。
Reactor模型中定义的三种角色:

  1. Reactor:负责监听和分配事件,将I/O事件分派给对应的Handler。新的事件包含连接建立就绪、读就绪、写就绪等。
  2. Acceptor:处理客户端新连接,并分派请求到处理器链中。
  3. Handler:将自身与事件绑定,执行非阻塞读/写任务,完成channel的读入,完成处理业务逻辑后,负责将结果写出channel。可用资源池来管理。
    Reactor处理请求的流程:
    读取操作:
    应用程序注册读就绪事件和相关联的事件处理器
    事件分离器等待事件的发生
    当发生读就绪事件的时候,事件分离器调用第一步注册的事件处理器

单Reactor单线程模型

Reactor线程负责多路分离套接字,accept新连接,并分派请求到handler。Redis使用单Reactor单进程的模型。
在这里插入图片描述

消息处理流程:

Reactor对象通过select监控连接事件,收到事件后通过dispatch进行转发。
如果是连接建立的事件,则由acceptor接受连接,并创建handler处理后续事件。
如果不是建立连接事件,则Reactor会分发调用Handler来响应。
handler会完成read->业务处理->send的完整业务流程。
单Reactor单线程模型只是在代码上进行了组件的区分,但是整体操作还是单线程,不能充分利用硬件资源。handler业务处理部分没有异步。

对于一些小容量应用场景,可以使用单Reactor单线程模型。但是对于高负载、大并发的应用场景却不合适,主要原因如下:

即便Reactor线程的CPU负荷达到100%,也无法满足海量消息的编码、解码、读取和发送。
当Reactor线程负载过重之后,处理速度将变慢,这会导致大量客户端连接超时,超时之后往往会进行重发,这更加重Reactor线程的负载,最终会导致大量消息积压和处理超时,成为系统的性能瓶颈。
一旦Reactor线程意外中断或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障。
为了解决这些问题,演进出单Reactor多线程模型。

单Reactor多线程模型

该模型在事件处理器(Handler)部分采用了多线程(线程池)。
在这里插入图片描述
消息处理流程:
Reactor对象通过Select监控客户端请求事件,收到事件后通过dispatch进行分发。
如果是建立连接请求事件,则由acceptor通过accept处理连接请求,然后创建一个Handler对象处理连接完成后续的各种事件。
如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来响应。
Handler只负责响应事件,不做具体业务处理,通过Read读取数据后,会分发给后面的Worker线程池进行业务处理。
Worker线程池会分配独立的线程完成真正的业务处理,如何将响应结果发给Handler进行处理。
Handler收到响应结果后通过send将响应结果返回给Client。
相对于第一种模型来说,在处理业务逻辑,也就是获取到IO的读写事件之后,交由线程池来处理,handler收到响应后通过send将响应结果返回给客户端。这样可以降低Reactor的性能开销,从而更专注的做事件分发工作了,提升整个应用的吞吐。

但是这个模型存在的问题:

多线程数据共享和访问比较复杂。如果子线程完成业务处理后,把结果传递给主线程Reactor进行发送,就会涉及共享数据的互斥和保护机制。
Reactor承担所有事件的监听和响应,只在主线程中运行,可能会存在性能问题。例如并发百万客户端连接,或者服务端需要对客户端握手进行安全认证,但是认证本身非常损耗性能。
为了解决性能问题,产生了第三种主从Reactor多线程模型。

3.主从Reactor多线程模型**

比起第二种模型,它是将Reactor分成两部分:
在这里插入图片描述

mainReactor负责监听server socket,用来处理网络IO连接建立操作,将建立的socketChannel指定注册给subReactor。
subReactor主要做和建立起来的socket做数据交互和事件业务处理操作。通常,subReactor个数上可与CPU个数等同。
Nginx、Swoole、Memcached和Netty都是采用这种实现。

消息处理流程:

从主线程池中随机选择一个Reactor线程作为acceptor线程,用于绑定监听端口,接收客户端连接
acceptor线程接收客户端连接请求之后创建新的SocketChannel,将其注册到主线程池的其它Reactor线程上,由其负责接入认证、IP黑白名单过滤、握手等操作
步骤2完成之后,业务层的链路正式建立,将SocketChannel从主线程池的Reactor线程的多路复用器上摘除,重新注册到Sub线程池的线程上,并创建一个Handler用于处理各种连接事件
当有新的事件发生时,SubReactor会调用连接对应的Handler进行响应
Handler通过Read读取数据后,会分发给后面的Worker线程池进行业务处理
Worker线程池会分配独立的线程完成真正的业务处理,如何将响应结果发给Handler进行处理
Handler收到响应结果后通过Send将响应结果返回给Client
总结
Reactor模型具有如下的优点:

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

引用

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

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

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

相关文章

BMS系统必要参数介绍

系统参数打印解释 (1)Battery Real Capacity:表示电池实际容量值(额定容量值是出厂给的,SOH电池健康度计算也可以用实际值/额定值) (2)Battery Remain Capacity:表示电池剩余容量值 (3)Battery SOC:电池剩余容量百分比…

头歌-机器学习 第12次实验 Adaboost算法

第1关:什么是集成学习 任务描述 本关任务:根据本节课所学知识完成本关所设置的选择题。 相关知识 为了完成本关任务,你需要掌握:1.什么是集成学习。 什么是集成学习 集成学习方法是一种常用的机器学习方法,分为b…

Unity 遮罩

编辑器版本 2017.2.3f1 学习Unity的三张遮罩方式 1. Mask 遮罩方式 首先,在界面上创建2个Image,一个命名Img_Mask,大小设置 400* 400, 一个命名Img_Show,大小设置500*500。 然后,给 Img_Mask添加Mask,选择Img_Mask,点击Add Com…

面试算法-170-二叉树的最大深度

题目 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3 解 class Solution {public int maxDepth(TreeNod…

卷积运算及实现

本文介绍卷积运算及实现。 1.定义 线性时不变系统的输出是输入样本与系统的冲激响应的卷积。这里假设输入样本为x(n),系统冲激响应为h(n),系统输出为y(n),则 线性卷积计算过程包含以下4个步骤: 1)折叠,关于l0&#…

The C programming language (second edition,KR) exercise(CHAPTER 2)

E x c e r c i s e 2 − 1 Excercise\quad 2-1 Excercise2−1&#xff1a;输出结果如图1和图2所示&#xff0c;这道练习题需要文章1和文章2的知识。 #include <stdio.h> #include <limits.h>float getFloat(char sign, unsigned char exp, unsigned mantissa); do…

抖音小店无货源怎么做?新型无货源玩法,帮商家躲避无货源处罚!

大家好&#xff0c;我是电商糖果 关于现在抖店的商家&#xff0c;是谈“无货源”色变&#xff0c;被平台罚怕了。 动不动就是扣分&#xff0c;扣2000的保证金&#xff0c;商家是苦不堪言。 又不舍得放弃抖音小店现在热度和风口。 糖果做抖音小店无货源有四年时间了&#xf…

WritableComparable排序案例实操

文章目录 WritableComparable排序概述第一个案例需求&#xff08;全排序&#xff09;代码实现结果分析 第二个案例需求&#xff08;二次排序&#xff09;问题分析和代码结果分析 第三个案例需求&#xff08;区内排序&#xff09;需求分析代码实现结果分析 WritableComparable排…

材料物理 笔记-5

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; 半…

激光测距漫反射板

激光测距漫反射板是一种重要的光学元件&#xff0c;广泛应用于工业测量、自动化控制、机器人导航等领域。自动驾驶技术的发展日新月异&#xff0c;其中激光测距技术在自动驾驶车辆中发挥着至关重要的作用。而激光测距反射板作为激光测距的关键组件之一&#xff0c;其性能和应用…

基于RKNN的YOLOv5安卓Demo

1.简介 基于RKNPU2 SDK 1.6.0版的安卓YOLOv5演示应用程序&#xff0c;选择图片进行对象检测并显示识别结果。 GitHub源码地址&#xff1a;https://github.com/shiyinghan/rknn-android-yolov5 2.实现过程 参考RKNN官方库RKNN Model Zoo提供的YOLOv5对象检测demo&#xff0c…

短袖怎么选质量好?5款质量好的短袖T恤

最近天气逐渐开始变热了&#xff0c;不少朋友都在考虑选什么短袖比较好。由于现在市面上的短袖品牌实在太多&#xff0c;并且还有很多做工差、面料不好的短袖混杂在其中&#xff0c;让大家挑选短袖十分困难。为此我特意进行了一次短袖测评&#xff0c;总结出几点选购方法&#…

C++ 之 newmat 矩阵运算库使用笔记

文章目录 Part.I IntroductionChap.I newmat 简介 Part.II 安装与编译Chap.I 直接使用源码Chap.II 基于 CMake 使用源码Chap.III 编译成库 Part.III 关于矩阵的构造与运算Chap.I 矩阵的构造与初始化Chap.II 矩阵的运算Chap.III 矩阵维数和类型的更改Chap.IV 矩阵最值统计 Refer…

可视化大屏的应用(11):智慧运维领域的得力助手

一、什么是智慧运维 智慧运维&#xff08;Smart Operations and Maintenance&#xff0c;简称智慧运维&#xff09;是一种利用先进的信息技术和数据分析手段&#xff0c;对设备、设施或系统进行监测、分析和优化管理的运维方式。它通过实时监测数据、智能分析和预测&#xff0…

【汇编语言实战】两个32位数的相加运算

C语言描述&#xff1a; #include <stdio.h> int main() { int a3,b2; printf("%d",ab); }汇编语言&#xff1a; include irvine32.inc .data a dword 32 b dword 33 .code main proc mov eax,a mov ebx,b add eax,ebx call writeint main endp end main运行结…

【Package Marking】UG475 FPGA 芯片丝印解析 AMD XILINX

Spartan 7 Devices Kintex 7 Device Virtex 7 Device 说明 条目定义Xilinx LogoXilinx 徽标、带有商标的 Xilinx 名称和商标注册状态。Pb-free Character对于 FFG、FBG 或 SBG 封装&#xff0c;器件右上角标有无铅字符&#xff0c;表示该器件使用无铅材料组制造&#xff0c;如…

Qt之QSS样式表

QSS简介 QSS&#xff08;Qt Style Sheet&#xff09;样式表是一种用于描述图形用户界面&#xff08;GUI&#xff09;样式的语言。它允许开发者为应用程序的控件定义视觉外观&#xff0c;例如颜色、字体、尺寸和布局等。 QSS 样式表的主要目的是提供一种简洁而灵活的方式来美化…

Java毕业设计 基于springboot vue撸宠平台 宠物系统

Java毕业设计 基于springboot vue撸宠平台 宠物系统 springboot撸宠平台 宠物系统 功能介绍 首页 图片轮播 用户或商家注册 用户或商家登录 登录验证码 店铺信息 店铺详情 店铺投诉 宠物信息 宠物详情 预订 退订 搜索 收藏 点赞 踩 评论 个人中心 更新信息 我的收藏 在线客服…

一文2500字从0到1使用JMeter进行接口测试教程!

安装 使用JMeter的前提需要安装JDK&#xff0c;需要JDK1.7以上版本目前在用的是JMeter5.2版本&#xff0c;大家可自行下载解压使用 运行 进入解压路径如E: \apache-jmeter-5.2\bin&#xff0c;双击jmeter.bat启动运行 启动后默认为英文版本&#xff0c;可通过Options – Cho…

【vim 学习系列文章 22 -- vim 实现 linux 多行快速标准注释】

文章目录 vim 实现 linux 多行快速标准注释 vim 实现 linux 多行快速标准注释 不多说了&#xff0c;直接上动图&#xff1a; 上代码&#xff1a; function! CommentBlock()" 获取Visual模式选中的起始和结束行号let old_start_line line("<")let old_end…