高性能网络IO模型

简介: 同步阻塞式IO开发简单,但在处理IO密集的并发任务时,非常浪费CPU资源,性能低;并且,当一个进程(线程)含有多个套接字上时,同步阻塞式IO会带来问题:因为同步阻塞式IO只支持进程(线程)阻塞在一个套接字上,其余套接字上的事件将得不到及时处理。

同步阻塞式IO开发简单,但在处理IO密集的并发任务时,非常浪费CPU资源,性能低;并且,当一个进程(线程)含有多个套接字上时,同步阻塞式IO会带来问题:因为同步阻塞式IO只支持进程(线程)阻塞在一个套接字上,其余套接字上的事件将得不到及时处理。

为解决这些问题,IO编程的世界诞生了更多的IO模型及实现,这些实现不仅可以用在网络编程中,同样可以用在本地IO编程中。

在此先做说明,阻塞与非阻塞、同步与异步是两组不同的概念。

而且下面说的模型,并不是绝对互斥的模型,它更像是一种方法,可以结合使用,比如IO复用一般与非阻塞IO搭配使用

1.1         IO复用

IO 复用技术是指,调用IO 复用的api(select、pselect、poll、epoll等)时,其阻塞在多个文件描述符(套接字)上,这与普通的阻塞式IO函数如:read、write、close等不同,这些函数都是阻塞在一个文件描述符上。以select为例,select等待多个文件描述符(套接字)上发生IO事件,可以设置等待超时,select只返回描述符就绪的个数(一般可认为是IO事件的个数),用户需要遍扫描整个描述符集处理IO时间。伪代码如下:

while(true){

    select(描述符集,超时值)

    for(fd in 描述符集合){

        if ( fd has IO事件){

            处理IO事件

        }

    }

}

真实的select要比此复杂,其可指定自己关心的描述符集,分读、写、出错三种描述符集。

Select的缺点很明显,当描述符集很大时,遍历一遍集合的耗时将会很大,因此会有一个FD_SETSIZE宏限制。后续的epoll则优化的此问题,只返回发生的IO事件及其关联的描述符。

1.2         非阻塞IO(NIO)

非阻塞式IO与阻塞式IO不同的是,非阻塞式IO发现IO暂不可进行时,不阻塞,而是直接返回错误。可结合轮询构成一种可用的模型,但很少见。伪代码如下:

while(true) {

    ret=recv(描述符)

    if(ret != 错误 && ret != 结束){

        处理IO事件

    }

}

 

1.3         信号(事件)驱动IO

信号驱动式IO在IO事件就绪后,向用户程序发送信号或者直接执行回调(调用用户进程空间中的函数),用户在回调函数中执行IO处理。纵观各种读写的IO操作,都是首先等待内核准备好数据或准备好存放数据的内核空间,然后执行内核空间与用户进程空间之间的数据拷贝。其中,信号驱动式IO模型就是在内存做好准备之后,向用户进程发送信号,通知用户进程执行剩下的数据拷贝的操作。以读事件为例,过程如图:

 

 

可以看到,信号驱动模式中,读取数据时,依然使用的是同步IO。因此epoll可以说是一种同步非阻塞的支持IO多路复用的IO模型,但是在linux kernel 2.6版本之后,epoll使用了mmap(文件内存映射系统调用),使得数据从内核拷贝到用户进程空间的过程被省略了,于是它有了下面要讲的异步IO的特点,由此进一步产生了epoll到底是异步非阻塞还是同步非阻塞IO模型的一些争议。

1.4         异步IO(AIO)

异步IO与信号驱动IO模型,仅在于1、通知发生在数据从内核空间读取到用户空间(读)或者数据从用户空间写入到内核空间之后(写)。2、使用的是异步的系统调用api接口。以读为例,过程如图:

 

 

可以看到异步IO实在内核已完成IO操作之后,才发起通知,时机不同于信号(事件)驱动式IO。Linux中异步IO系统调用皆以aio_*开头。操作完成之后的通知方式可以是信号,也可以是用户进程空间中的回调函数,皆可通过aiocb结构体设置。目前linux 虽然已有aio函数,但是即使是epoll也并没有直接使用aio,而是通过非阻塞+mmap达到了伪AIO的效果,这与windows iocp和FreeBSD的kqueue纯异步的方案是不同的,普遍的测试结果,epoll性能比iocp还是有微小的差距。

目录
相关文章
|
5月前
|
网络协议 算法 Java
基于Reactor模型的高性能网络库之Tcpserver组件-上层调度器
TcpServer 是一个用于管理 TCP 连接的类,包含成员变量如事件循环(EventLoop)、连接池(ConnectionMap)和回调函数等。其主要功能包括监听新连接、设置线程池、启动服务器及处理连接事件。通过 Acceptor 接收新连接,并使用轮询算法将连接分配给子事件循环(subloop)进行读写操作。调用链从 start() 开始,经由线程池启动和 Acceptor 监听,最终由 TcpConnection 管理具体连接的事件处理。
224 2
|
5月前
|
Java Linux API
IO模型
BIO、NIO、AIO是Java中处理网络I/O的三种模型。BIO为阻塞式,每个连接需单独线程,高并发下性能受限;NIO通过非阻塞与多路复用提升并发能力,少量线程可处理大量请求;AIO进一步实现异步非阻塞,数据复制时线程可释放,由回调机制处理后续操作。三者适用于不同场景,BIO易用但低效,NIO高效但复杂,AIO理论性能更优但目前在Linux上仍依赖多路复用实现。Java 21引入虚拟线程后,BIO也可兼具高性能与易编写特性。
185 2
|
5月前
基于Reactor模型的高性能网络库之Tcpconnection组件
TcpConnection 由 subLoop 管理 connfd,负责处理具体连接。它封装了连接套接字,通过 Channel 监听可读、可写、关闭、错误等
174 1
|
5月前
|
负载均衡 算法 安全
基于Reactor模式的高性能网络库之线程池组件设计篇
EventLoopThreadPool 是 Reactor 模式中实现“一个主线程 + 多个工作线程”的关键组件,用于高效管理多个 EventLoop 并在多核 CPU 上分担高并发 I/O 压力。通过封装 Thread 类和 EventLoopThread,实现线程创建、管理和事件循环的调度,形成线程池结构。每个 EventLoopThread 管理一个子线程与对应的 EventLoop(subloop),主线程(base loop)通过负载均衡算法将任务派发至各 subloop,从而提升系统性能与并发处理能力。
313 3
|
5月前
|
JSON 监控 网络协议
干货分享“对接的 API 总是不稳定,网络分层模型” 看电商 API 故障的本质
本文从 OSI 七层网络模型出发,深入剖析电商 API 不稳定的根本原因,涵盖物理层到应用层的典型故障与解决方案,结合阿里、京东等大厂架构,详解如何构建高稳定性的电商 API 通信体系。
|
5月前
基于Reactor模式的高性能网络库github地址
https://github.com/zyi30/reactor-net.git
144 0
|
2月前
|
机器学习/深度学习 数据采集 人工智能
深度学习实战指南:从神经网络基础到模型优化的完整攻略
🌟 蒋星熠Jaxonic,AI探索者。深耕深度学习,从神经网络到Transformer,用代码践行智能革命。分享实战经验,助你构建CV、NLP模型,共赴二进制星辰大海。
|
3月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
244 2
|
3月前
|
机器学习/深度学习 并行计算 算法
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
|
3月前
|
监控 前端开发 安全
Netty 高性能网络编程框架技术详解与实践指南
本文档全面介绍 Netty 高性能网络编程框架的核心概念、架构设计和实践应用。作为 Java 领域最优秀的 NIO 框架之一,Netty 提供了异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本文将深入探讨其 Reactor 模型、ChannelPipeline、编解码器、内存管理等核心机制,帮助开发者构建高性能的网络应用系统。
245 0

热门文章

最新文章