高性能网络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还是有微小的差距。

目录
相关文章
|
24天前
|
缓存 Java Linux
网络IO模型总结
网络IO模型总结
38 0
|
2月前
|
NoSQL Java 关系型数据库
字节跳动三面拿offer:网络+IO+redis+JVM+GC+红黑树+数据结构
5G的到来证明了互联网行业发展一如既往的快,作为一名开发人员(Java岗)梦想自然是互联网行业的大厂,这次有幸获得面试字节跳动的机会,为此我也做出了准备在面试前一个月就开始做准备了,也很荣幸的拿到了字节跳动的offer,这里分享一份字节跳动三面过程!
|
2月前
|
缓存 网络协议 Linux
深入理解Linux网络——本机网络IO
前面的章节深度分析了网络包的接收,也拆分了网络包的发送,总之收发流程算是闭环了。不过还有一种特殊的情况没有讨论,那就是接收和发送都在本机进行。而且实践中这种本机网络IO出现的场景还不少,而且还有越来越多的趋势。例如LNMP技术栈中的nginx和php-fpm进程就是通过本机来通信的,还有流行的微服务中sidecar模式也是本机网络IO。
|
3月前
|
缓存 网络协议 算法
深入剖析Linux网络设计中网络IO的重要角色
本文深入剖析了Linux网络设计中网络IO的重要角色。网络IO在Linux系统中扮演着关键的角色,负责管理和协调数据在网络中的传输。我们将探讨网络IO的基本概念、作用和实现原理。首先介绍了Linux网络IO的核心组件,如套接字、文件描述符和缓冲区,以及它们在网络通信中的作用。然后详细解释了常见的网络IO模型,包括阻塞IO、非阻塞IO、多路复用IO和异步IO,并比较它们的特点和适用场景。紧接着,我们深入研究了Linux内核中网络IO的实现细节,包括事件驱动机制、IO调度算法和数据传输过程。
80 1
深入剖析Linux网络设计中网络IO的重要角色
|
3月前
|
监控 大数据 Linux
高性能网络设计秘笈:深入剖析Linux网络IO与epoll
本文介绍了网络IO模型,引入了epoll作为Linux系统中高性能网络编程的核心工具。通过分析epoll的特点与优势,并给出使用epoll的注意事项和实践技巧,该文章为读者提供了宝贵的指导。通过掌握这些知识,读者能够构建高效、可扩展和稳定的网络应用,提供出色的用户体验。
63 0
高性能网络设计秘笈:深入剖析Linux网络IO与epoll
|
3月前
|
监控 网络协议 Unix
突破网络瓶颈:提升性能的必备技术——Linux网络IO与select详解
本文通过对Linux网络IO和select的详细讨论,帮助读者深入理解了这些关键概念,并展示了select函数在构建高效网络应用中的重要性和灵活性。对于想要提升网络编程技能的开发者来说,这些知识将会是宝贵的参考和实践指南。
142 1
突破网络瓶颈:提升性能的必备技术——Linux网络IO与select详解
|
5月前
|
监控 网络协议 Linux
【计算机网络】高并发业务必备的Linux网络IO模型
【计算机网络】高并发业务必备的Linux网络IO模型
【计算机网络】高并发业务必备的Linux网络IO模型
|
5月前
|
运维
一键分析硬件/IO/全国网络性能脚本(强推)
一键分析硬件/IO/全国网络性能脚本(强推)
|
6月前
|
监控 前端开发 Java
网络编程二-LINUX网络IO模型
网络编程二-LINUX网络IO模型
58 0
|
8月前
|
Python
Python编程:aiohttp和requests网络io性能比较
使用4 种方式 对网络发起10次请求,进行10次耗时测试
54 0
Python编程:aiohttp和requests网络io性能比较
相关产品
云迁移中心
推荐文章
更多