加入收藏 | 设为首页 | 会员中心 | 我要投稿 驾考网 (https://www.jiakaowang.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 系统 > 正文

linux网络中五种不看不懂的IO模型,想成为大牛,不可不看

发布时间:2023-03-02 11:02:04 所属栏目:系统 来源:
导读:前言
你知道Netty的功力为何那么高吗?你知道Redis为什么单线程如此之快吗?这都和底层的网络IO模型有关系,所以掌握网络IO模型真的很重要,是一个基础,对你更好的理解其他应用帮助非常大,所以今天我们就好好一条一
前言
你知道Netty的功力为何那么高吗?你知道Redis为什么单线程如此之快吗?这都和底层的网络IO模型有关系,所以掌握网络IO模型真的很重要,是一个基础,对你更好的理解其他应用帮助非常大,所以今天我们就好好一条一条来聊聊Linux的5种常用网络IO优化模型。

IO的性能瓶颈主要是下面两个阶段:

准备阶段,指数据从网络网卡或本地存储器读取到内核的过程
复制阶段,指将内核缓冲区中的数据拷贝至用户的进程缓冲区
所以,Linux系统中提供了五种IO模型来提高性能,它们分别为BIO、NIO、多路复用、信号驱动、AIO,从性能上来说,它们属于依次递进的关系,但越靠后的IO模型实现也越为复杂。

1. 阻如IO模型BIO
当用户应用线程调用linux操作系统的recvfrom​函数读取数据的时候,如果内核的buffer​内存中没有数据,那么用户线程会阻塞等待,直到内核的buffer​内存中有数据了,才去将内核的buffer内存中的数据拷贝到用户应用内存中。

打比方理解:

比如你给女神发一条短信, 说我来找你了, 然后就默默的一直等着女神下楼, 这个期间除了等待你不会做其他事情, 属于备胎做法。也就是说线程会一直阻塞等待内核把数据准备好,然后将数据copy到用户空间。

优点:

开发简单,容易入门;
在阻塞等待期间,用户线程挂起,在挂起期间不会占用CPU资源。
缺点:

在BIO这种模型中,为了支持并发请求,通常会采用多线程的方式,并发过高时会导致创建大量线程,造成频繁的上下文切换,甚至系统崩溃。

2. 非阻碍IO模型NIO
当用户应用线程调用linux操作系统的recvfrom​函数读取数据的时候,如果内核的buffer​内存中没有数据,那么用户线程会直接拿到结果(没有数据)而不会阻塞等待,于是又会发起一次recvfrom函数调用,直到内核的buffer内存中有数据了,才去将内核的buffer内存中的数据拷贝到用户应用内存中。

在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。

打比方理解:

比如你给女神发短信, 如果不回, 接着再发, 一直发到女神下楼, 这个期间你除了发短信等待不会做其他事情, 属于专一做法。同理,用户线程无需等待内核数据准备结果,直接返回,然后通过轮询去问结果,如果结果为准备好,进程把数据copy到用户空间。

优点:

每次发起IO调用,在内核等待数据的过程中可以立即返回,用户线程不会阻塞。
缺点:

多个线程不断轮询内核是否有数据,会占用大量CPU时间。
NIO相对来说较为鸡肋,因此目前大多数的NIO技术并非采用这种多线程的模型,而是基于单线程的多路复用模型实现的,Java中支持的NIO模型亦是如此。

3. 多路复用IO模型
前面提到NIO由于线程在不断的轮询查看数据是否准备就绪,造成CPU开销较大。既然说是由于大量无效的轮询造成CPU占用过高,那么等内核中的数据准备好了之后,再去询问数据是否就绪是不是就可以了?答案是Yes。这就是我们多路复用IO模型的设计思想。

IO多路复用就是利用Linux的内核单线程去监听多个文件描述符,并在某个文件描述符可读、可写的时候接收到通知,避免无效的等待,充分利用CPU资源。

select​时间复杂度O(n),它仅仅知道了,有I/O事件发生了,却并不知道是哪几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长,而且最多支持的连接数量是1024个。
poll​(翻译:轮询)时间复杂度O(n),poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的。
epoll​时间复杂度O(1),epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))。
打个比方理解:

IO多路复用相当于找一个宿管大妈来帮你监视下楼的女生, 这个期间你可以些其他的事情. 例如可以顺便看看其他妹子,玩玩王者荣耀, 上个厕所等等。IO复用又包括 select、poll、epoll 模式。那么它们的区别是什么?

select​大妈 每一个女生下楼, select大妈都不知道这个是不是你的女神, 她需要一个一个询问, 并且select大妈能力还有限, 最多一次帮你监视1024个妹子。
poll大妈不限制盯着女生的数量, 只要是经过宿舍楼门口的女生, 都会帮你去问是不是你女神。
epoll大妈不限制盯着女生的数量, 并且也不需要一个一个去问. 那么如何做呢? epoll大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字, 只要女生下楼了, epoll大妈就知道这个是不是你女神了, 然后大妈再通知你。
通知你之后,你需要到女生宿舍门口,把女神带回自己宿色。

优点:

系统不必创建维护大量线程,只使用一个线程,一个选择器即可同事处理成千上万个连接,大大减少系统开销。
缺点:

本质上,它还是同步的,数据准备好后,拷贝阶段依然是阻塞的。
如果处理的连接数不是很高的话,使用select/epoll的web server​不一定比使用mutil-threading + blocking IO的web server​性能更好,可能延迟还更大。select/epoll 的优势并不是对于单个连接能处理得更好,而是在于性能更多的连接,比如Redis、Netty都是采用这种IO模型。都是采用这种io模型。这种方法的好处是可以同时处理多个连接,但是缺点是需要更多的cpu资源,并且对于一些特殊的场景会有一定的限制。
 

(编辑:驾考网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章