什么是IO多路复用?Nginx的处理机制

先来说一下什么是IO复用?

IO复用解决的就是并发行的问题,比如多个用户并发访问一个WEB网站,对于服务端后台而言就会产生多个请求,处理多个请求对于中间件就会产生多个IO流对于系统的读写。那么对于IO流请求操作系统内核有并行处理和串行处理的概念,串行处理的方式是一个个处理,前面的发生阻塞,就没办法完成后面的请求。这个时候我们必须考虑并行的方式完成整个IO流的请求来实现最大的并发和吞吐,这时候就是用到IO复用技术。IO复用就是让一个Socket来作为复用完成整个IO流的请求。当然实现整个IO流的请求多线程的方式就是其中一种。

***下面是一些举例,让你更清楚的了解什么是IO多路复用***

举例:在教室里面有一个老师同时给学生出一道题目,检查每个学生做的是否正确,这时候老师可以选择一个一个学生的去问学生是否做完。如果A学生没做完,那么再问B学生,B学生没做完再问C学生,挨个问下去,如果发现问道某一个学生,某一个学生说做完的时候,这时候再给当下学生解答。那么这时候会发现,如果一个学生发生了阻塞,阻塞在一个学生下,其他学生就会耽误了,这时候对整个课堂效率就底下。这就是串行请求类处理。
那么多线程呢?
再举例:也是这个场景,给学生出题让学生解答。这个老师学会了分身术,每个老师对每个学生进行监听,看学生是否答题完并作出解答,这样效率就高了。这就是多线程进行IO流处理,那么多线程IO流就会产生一定的消耗,资源问题的存在。
什么是IO多路复用呢?
再再举例:同样也是答题场景,其实就是改为了由学生来主动跟老师汇报,比如学生B答完了,这时候老师跟B进行解答,因为B学习效率高,其他学生还在做题,这时候给学生B解答完后,老师再给第二个学生解答,这时候学生主动汇报,效率就高了。这种方式就是IO多路复用的方式。特点:学生主动汇报。
对于操作系统而言,IO多路复用就是要完成操作系统IO的请求。对于IO文件的请求,当一个IO流要进行文件处理的时候,要获取一组文件的描述符,当文件描述符还没有就绪时,那么它就在等待,直到描述符一旦就绪,马上上报系统通知的机制,告诉应用程序我准备就绪,你可以来操作了。这就是IO多路复用的方式。
这种机制处理起来就很高效,多路复用就是在一个线程里,交替并发的完成。复用的就是一个线程。

------------------------下面来看一下知乎帖子几个前辈给出的比较粗俗易懂的解答------------------------

李遥:

你有N个不知道什么时候来水的水龙头需要接水,你根据某种信号一会儿拧这个龙头,一会儿拧那个龙头把水都接了就是多路复用(一个线程)。使用残像拳在每个水龙头前派一个你的分身蹲守就是Threaded IO。其实后者也没啥不好,因为未来的内核会消除上下文切换的软硬件性能损耗。

Leslie:

要弄清问题先要知道问题的出现原因

原因:
由于进程的执行过程是线性的(也就是顺序执行),当我们调用低速系统I/O(read,write,accept等等),进程可能阻塞,此时进程就阻塞在这个调用上,不能执行其他操作.阻塞很正常. 接下来考虑这么一个问题: 一个服务器进程和一个客户端进程通信,服务器端read(sockfd1,bud,bufsize),此时客户端进程没有发送数据,那么read(阻塞调用)将阻塞直到客户端调用write(sockfd,but,size) 发来数据. 在一个客户和服务器通信时这没什么问题,当多个客户与服务器通信时,若服务器阻塞于其中一个客户sockfd1,当另一个 客户的数据到达套接字sockfd2时,服务器不能处理,仍然阻塞在read(sockfd1,...)上;此时问题就出现了,不能及时处理另一个客户的服务,咋么办?I/O多路复用来解决!
I/O多路复用:
继续上面的问题,有多个客户连接, sockfd1,sockfd2,sockfd3..sockfdn 同时监听这n个客户,当其中有一个发来消息 时就从select的阻塞中返回,然后就调用read读取收到消息的sockfd,然后又循环回select 阻塞;这样就不会因为阻塞在其中一个上而不能处理另一个客户的消息
Q:
那这样子,在读取socket1的数据时,如果其它socket有数据来,那么也要等到socket1读取完了才能继续读取其它socket的数据吧。那不是也阻塞住了吗?而且读取到的数据也要开启线程处理吧,那这和多线程IO有什么区别呢?
A:
1.CPU本来就是线性的不论什么都需要顺序处理并行只能是多核CPUhttp:
2.io多路复用本来就是用来解决对多个I/O监听时,一个I/O阻塞影响其他I/O的问题,跟多线程没关系.
3.跟多线程相比较,线程切换需要切换到内核进行线程切换,需要消耗时间和资源. 而I/O多路复用不需要切换线/进程,效率相对较高,特别是对高并发的应用nginx就是用I/O多路复用,故而性能极佳.但多线程编程逻辑和处理上比I/O多路复用简单.而I/O多路复用处理起来较为复杂.

某匿名用户:

这些名词比较绕口,理解涵义就好。一个epoll场景:一个酒吧服务员(一个线程),前面趴了一群醉汉,突然一个吼一声“倒酒”(事件),你小跑过去给他倒一杯,然后随他去吧,突然又一个要倒酒,你又过去倒上,就这样一个服务员服务好多人,有时没人喝酒,服务员处于空闲状态,可以干点别的玩玩手机。至于epoll与select,poll的区别在于后两者的场景中醉汉不说话,你要挨个问要不要酒,没时间玩手机了。io多路复用大概就是指这几个醉汉共用一个服务员。

某匿名用户:

1 人赞同了该回答
IO模式一般分为同步IO和异步IO. 同步IO会阻塞进程, 异步IO不会阻塞进程. 目前linux上大部分用的是同步IO, 异步IO在linux上目前还不成熟, 不过windows的iocp算是真正的异步IO。
同步IO又分为阻塞IO, 非阻塞IO, IO多路复用. What? 同步IO明明会阻塞进程,为什么也包括非阻塞IO? 因为非阻塞IO虽然在请求数据时不阻塞, 但真正数据来临时,也就是内核数据拷贝到用户数据时, 此时进程是阻塞的.
那么这些IO模式的区别分别是什么? 接下来举个小例子来说明. 假设你现在去女生宿舍楼找自己的女神, 但是你只知道女神的手机号,并不知道女神的具体房间
先说同步IO的情况,
1. 阻塞IO, 给女神发一条短信, 说我来找你了, 然后就默默的一直等着女神下楼, 这个期间除了等待你不会做其他事情, 属于备胎做法.
2. 非阻塞IO, 给女神发短信, 如果不回, 接着再发, 一直发到女神下楼, 这个期间你除了发短信等待不会做其他事情, 属于专一做法.
3. IO多路复用,是找一个宿管大妈来帮你监视下楼的女生, 这个期间你可以些其他的事情. 例如可以顺便看看其他妹子,玩玩王者荣耀, 上个厕所等等。IO复用又包括 select, poll, epoll 模式. 那么它们的区别是什么?
3.1 select大妈每一个女生下楼, select大妈都不知道这个是不是你的女神, 她需要一个一个询问, 并且select大妈能力还有限, 最多一次帮你监视1024个妹子
3.2 poll大妈不限制盯着女生的数量, 只要是经过宿舍楼门口的女生, 都会帮你去问是不是你女神
3.3 epoll大妈不限制盯着女生的数量, 并且也不需要一个一个去问. 那么如何做呢? epoll大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字, 只要女生下楼了, epoll大妈就知道这个是不是你女神了, 然后大妈再通知你.
上面这些同步IO有一个共同点就是, 当女神走出宿舍门口的时候, 你已经站在宿舍门口等着女神的, 此时你属于阻塞状态
接下来是异步IO的情况
你告诉女神我来了, 然后你就去王者荣耀了, 一直到女神下楼了, 发现找不见你了, 女神再给你打电话通知你, 说我下楼了, 你在哪呢? 这时候你才来到宿舍门口. 此时属于逆袭做法。

 

总结:
有多个客户连接,1、2、3、4、5、N同时监听这M个客户,当其中有一个发来消息时就从阻塞中返回,然后就进行 请求处理,然后又循环回阻塞;这样就不会因为阻塞在其中一个上而不能处理另一个客户的消息

 

具体帖子地址:https://www.zhihu.com/question/32163005

posted @ 2018-03-08 15:54  温柔的风  阅读(4008)  评论(0编辑  收藏