网络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

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

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

相关文章

【从浅学到熟知Linux】进程状态与进程优先级(含进程R/S/T/t/D/X/Z状态介绍、僵尸进程、孤儿进程、使用top及renice调整进程优先级)

🏠关于专栏:Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程及数据库等内容。 🎯每天努力一点点,技术变化看得见 文章目录 进程状态进程状态查看R运行状态(running)S睡眠状态(sleeping&a…

GT收发器64B66B协议(2)自定义PHY设计

文章目录 前言一、设计框图二、GT_module三、PHY_module3.1、PHY_tx模块3.2、PHY_rx_bitsync模块3.3、PHY_rx模块 四、上板测试总结 前言 有了对64B66B协议的认识以及我们之前设计8B10B自定义PHY的经验,本文开始对64B66B自定义PHY的设计 一、设计框图 二、GT_modu…

Harmony鸿蒙南向驱动开发-UART

UART指异步收发传输器(Universal Asynchronous Receiver/Transmitter),是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 两个UART设备的连接示意图如下,UART与其他模块一般用2线&a…

数据结构初阶:栈和队列

栈 栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。 栈中的数据元素遵守后进先出 LIFO ( Last In First Out )的原则。…

为什么每个人都需要了解这些数据加密技术?

在数字时代,数据加密技术不仅对保护企业的商业秘密至关重要,也是个人隐私安全的重要屏障。随着技术的进步和网络犯罪的增加,数据加密已经成为了信息安全领域的一个热点议题。以下是探讨为什么每个人都需要了解这些数据加密技术的几个主要原因…

SpringBoot启动时banner设置

SpringBoot启动时banner设置 1.操作步骤2.各种banner图像 1.操作步骤 在application.properties文件中设置新的banner对于的文件位置,最好放在resources目录下 spring.banner.locationbanner.txt2.各种banner图像 (1)经典大佛图 具体txt文…

[通俗易懂]《动手学强化学习》学习笔记2-第2、3、4章

文章目录 前言小总结(前文回顾)第二章 多臂老虎机2.2.2形式化描述 第三章 马尔可夫决策过程3.6 占用度量 代码3.6 占用度量 定理2 第四章 动态规划算法4.3.3 策略迭代算法 代码 总结 前言 参考: 《动手学强化学习》作者:张伟楠&a…

为什么要部署IP SSL证书?怎么申请?

我们需要知道什么是IP SSL证书。SSL,全称为Secure Sockets Layer,即安全套接层,是为网络通信提供安全及数据完整性的一种安全协议。而IP SSL证书就是基于SSL协议的一种证书,它能够为网站和用户的数据传输提供加密处理,…

Prometheus-Grafana基础篇安装绘图

首先Prometheus安装 1、下载 https://prometheus.io/download/ 官网路径可以去这儿下载 2、如图: 3.解压: tar -xf prometheus-2.6.1.linux-amd64 cd prometheus-2.6.1.linux-amd64 4.配置文件说明: vim prometheus.yml 5.启动Promethe…

OpenHarmony NAPI 框架生成工具实现流程

NAPI 框架生成工具 可以根据用户指定路径下的 ts(typescript)接口文件一键生成 NAPI 框架代码、业务代码框架、GN 文件等。在开发 JS 应用与 NAPI 间接口时,底层框架开发者无需关注 Nodejs 语法、C 与 JS 之间的数据类型转换等上层应用转换逻辑,只关注底…

论文| Convolutional Neural Network-based Place Recognition - 2014

2014-Convolutional Neural Network-based Place Recognition

Qt plugin 开发UI界面插件

目录 1.创建接口 2.创建插件 3.创建插件界面 4.插件实现 5.创建应用工程 6.应用插件 1.创建接口 打开QtCreater,点击左上角“文件”->新建文件或项目,在弹窗中选择C/CHeader File。 输入文件名,选好路径(可自行设置名称…

Golang | Leetcode Golang题解之第16题最接近的三数之和

题目&#xff1a; 题解&#xff1a; func threeSumClosest(nums []int, target int) int {sort.Ints(nums)var (n len(nums)best math.MaxInt32)// 根据差值的绝对值来更新答案update : func(cur int) {if abs(cur - target) < abs(best - target) {best cur}}// 枚举 a…

BM96 主持人调度(二)(贪心算法)

一开始写的时候忘了给start、end数组赋值了 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** 计算成功举办活动需要多少名主持人* param n int整型 有n个活动* param start…

Qt——示波器/图表 QCustomPlot

一、介绍 QCustomPlot是一个用于绘图和数据可视化的Qt C小部件。它没有进一步的依赖关系&#xff0c;提供友好的文档帮助。这个绘图库专注于制作好看的&#xff0c;出版质量的2D绘图&#xff0c;图形和图表&#xff0c;以及为实时可视化应用程序提供高性能。QCustomPlot可以导出…

解决 VSCode 编辑器点击【在集成终端中打开】出现新的弹框

1、问题描述 在 VSCode 的项目下&#xff0c;鼠标右键&#xff0c;点击【在集成终端中打开】&#xff0c;出现新的一个弹框。新版的 VSCode 会有这个问题&#xff0c;一般来说我们都希望终端是在 VSCode 的控制台中打开的&#xff0c;那么如何关闭这个弹框呢&#xff1f; 2、解…

浅谈一下数据接口怎么方便我们的工作

最近一段时间&#xff0c;一直在折腾自己工作上面的一些事情&#xff0c;这几天终于稍微闲下来去做一份表格。 这份表格是基于一款游戏的数据接口去做一个动态的运算&#xff0c;核算出相关的利润率等等的数据。那么我们今天来具体聊聊Excel的获取数据功能。 现在比较多应用都…

VUE3和SpringBoot实现ChatGPT页面打字效果SSE流式数据展示

在做这个功能之前&#xff0c;本人也是走了很多弯路&#xff08;花了好几天才搞好&#xff09;&#xff0c;你能看到本篇博文&#xff0c;那你就是找对地方了。百度上很多都是使用SseEmitter这种方式&#xff0c;这种方式使用的是websocket&#xff0c;使用这种方式就搞复杂了&…

Java项目:基于SSM+vue框架实现的人力资源管理系统设计与实现(源码+数据库+毕业论文+任务书)

一、项目简介 本项目是一套基于SSM框架实现的人力资源管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功能…

WEB漏洞-文件上传之WAF绕过及安全修复

#上传参数解析&#xff1a; Content-disposition&#xff1a;一般不可更改 Name&#xff1a;表单参数值&#xff0c;不能更改&#xff08;更改需要达到统一&#xff09; Filename&#xff1a;文件名&#xff0c;可以更改 Content-type&#xff1a;文件MIME&#xff0c;视情…