多路复用,讲的很明白

article/2025/10/19 10:43:52

作者:罗志宇
链接:https://www.zhihu.com/question/32163005/answer/55772739
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

假设你是一个机场的空管, 你需要管理到你机场的所有的航线, 包括进港,出港, 有些航班需要放到停机坪等待,有些航班需要去登机口接乘客。

你会怎么做?

最简单的做法,就是你去招一大批空管员,然后每人盯一架飞机, 从进港,接客,排位,出港,航线监控,直至交接给下一个空港,全程监控。

那么问题就来了:

  • 很快你就发现空管塔里面聚集起来一大票的空管员,交通稍微繁忙一点,新的空管员就已经挤不进来了。
  • 空管员之间需要协调,屋子里面就1, 2个人的时候还好,几十号人以后 ,基本上就成菜市场了。
  • 空管员经常需要更新一些公用的东西,比如起飞显示屏,比如下一个小时后的出港排期,最后你会很惊奇的发现,每个人的时间最后都花在了抢这些资源上。

 

现实上我们的空管同时管几十架飞机稀松平常的事情, 他们怎么做的呢?
他们用这个东西

这个东西叫flight progress strip. 每一个块代表一个航班,不同的槽代表不同的状态,然后一个空管员可以管理一组这样的块(一组航班),而他的工作,就是在航班信息有新的更新的时候,把对应的块放到不同的槽子里面。

 

这个东西现在还没有淘汰哦,只是变成电子的了而已。。

是不是觉得一下子效率高了很多,一个空管塔里可以调度的航线可以是前一种方法的几倍到几十倍。

如果你把每一个航线当成一个Sock(I/O 流), 空管当成你的服务端Sock管理代码的话.

第一种方法就是最传统的多进程并发模型 (每进来一个新的I/O流会分配一个新的进程管理。)
第二种方法就是I/O多路复用 (单个线程,通过记录跟踪每个I/O流(sock)的状态,来同时管理多个I/O流 。)

其实“I/O多路复用”这个坑爹翻译可能是这个概念在中文里面如此难理解的原因。所谓的I/O多路复用在英文中其实叫 I/O multiplexing. 如果你搜索multiplexing啥意思,基本上都会出这个图:

于是大部分人都直接联想到"一根网线,多个sock复用" 这个概念,包括上面的几个回答, 其实不管你用多进程还是I/O多路复用, 网线都只有一根好伐。多个Sock复用一根网线这个功能是在内核+驱动层实现的

重要的事情再说一遍: I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流. 发明它的原因,是尽量多的提高服务器的吞吐能力。

 

是不是听起来好拗口,看个图就懂了.

 


在同一个线程里面, 通过拨开关的方式,来同时传输多个I/O流, (学过EE的人现在可以站出来义正严辞说这个叫“时分复用”了)。

 

什么,你还没有搞懂“一个请求到来了,nginx使用epoll接收请求的过程是怎样的”, 多看看这个图就了解了。提醒下,ngnix会有很多链接进来, epoll会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相应的代码处理。

------------------------------------------
了解这个基本的概念以后,其他的就很好解释了。

select, poll, epoll 都是I/O多路复用的具体的实现,之所以有这三个鬼存在,其实是他们出现是有先后顺序的。

I/O多路复用这个概念被提出来以后, select是第一个实现 (1983 左右在BSD里面实现的)。

select 被实现以后,很快就暴露出了很多问题。

  • select 会修改传入的参数数组,这个对于一个需要调用很多次的函数,是非常不友好的。
  • select 如果任何一个sock(I/O stream)出现了数据,select 仅仅会返回,但是并不会告诉你是那个sock上有数据,于是你只能自己一个一个的找,10几个sock可能还好,要是几万的sock每次都找一遍,这个无谓的开销就颇有海天盛筵的豪气了。
  • select 只能监视1024个链接, 这个跟草榴没啥关系哦,linux 定义在头文件中的,参见FD_SETSIZE。
  • select 不是线程安全的,如果你把一个sock加入到select, 然后突然另外一个线程发现,尼玛,这个sock不用,要收回。对不起,这个select 不支持的,如果你丧心病狂的竟然关掉这个sock, select的标准行为是。。呃。。不可预测的, 这个可是写在文档中的哦.

“If a file descriptor being monitored by select() is closed in another thread, the result is unspecified”
霸不霸气

于是14年以后(1997年)一帮人又实现了poll, poll 修复了select的很多问题,比如

  • poll 去掉了1024个链接的限制,于是要多少链接呢, 主人你开心就好。
  • poll 从设计上来说,不再修改传入数组,不过这个要看你的平台了,所以行走江湖,还是小心为妙。

其实拖14年那么久也不是效率问题, 而是那个时代的硬件实在太弱,一台服务器处理1千多个链接简直就是神一样的存在了,select很长段时间已经满足需求。

但是poll仍然不是线程安全的, 这就意味着,不管服务器有多强悍,你也只能在一个线程里面处理一组I/O流。你当然可以那多进程来配合了,不过然后你就有了多进程的各种问题。

于是5年以后, 在2002, 大神 Davide Libenzi 实现了epoll.

epoll 可以说是I/O 多路复用最新的一个实现,epoll 修复了poll 和select绝大部分问题, 比如:

  • epoll 现在是线程安全的。
  • epoll 现在不仅告诉你sock组里面数据,还会告诉你具体哪个sock有数据,你不用自己去找了。

 

epoll 当年的patch,现在还在,下面链接可以看得到:
/dev/epoll Home Page

贴一张霸气的图,看看当年神一样的性能(测试代码都是死链了, 如果有人可以刨坟找出来,可以研究下细节怎么测的).


横轴Dead connections 就是链接数的意思,叫这个名字只是它的测试工具叫deadcon. 纵轴是每秒处理请求的数量,你可以看到,epoll每秒处理请求的数量基本不会随着链接变多而下降的。poll 和/dev/poll 就很惨了。

 

可是epoll 有个致命的缺点。。只有linux支持。比如BSD上面对应的实现是kqueue。

其实有些国内知名厂商把epoll从安卓里面裁掉这种脑残的事情我会主动告诉你嘛。什么,你说没人用安卓做服务器,尼玛你是看不起p2p软件了啦。

而ngnix 的设计原则里面, 它会使用目标平台上面最高效的I/O多路复用模型咯,所以才会有这个设置。一般情况下,如果可能的话,尽量都用epoll/kqueue吧。

详细的在这里:
Connection processing methods

PS: 上面所有这些比较分析,都建立在大并发下面,如果你的并发数太少,用哪个,其实都没有区别。 如果像是在欧朋数据中心里面的转码服务器那种动不动就是几万几十万的并发,不用epoll我可以直接去撞墙了


http://chatgpt.dhexx.cn/article/FBo8rOj2.shtml

相关文章

全网最详细的 I/O 多路复用解析

前言 IO多路复用目前在大厂的面试中,一般在两个地方可能会被问到,一个是在问到网络这一块的时候,另一个是在问到 Redis 这一块的时候,因为 Redis 底层也是使用了IO多路复用,所以整体来说 IO多路复用,也算是…

计算机网络基础之多路复用技术

温故: 1、单工传输:单工传输只支持数据在一个方向上传输,数据传送只能在一个方向上进行,任何时候都不能改变方向,就像公路上的单行道,例如无线电广播。 2、半双工传输:半双工传输允许数据在两个方向上传输&…

《JAVA核心知识》学习笔记(JVM)-1

JVM (1) 基本概念: JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、 一个垃圾回收,堆 和 一个存储方法域。 JVM 是运行在操作系统之上的,它与硬件没有直接 的交互 Hotspot JVM 后台运行的系统线…

多路复用技术概述

概述频分复用(Frequency Division Multiplexing)时分复用(Time Division Multiplexing)波分复用(Wave Division Multiplexing)码分复用(Code Division Multiplexing) 概述 数据是在物理链路的信道中传输的,通常一条链路上会有多条信道。在默认情况下,一…

计算机网络-多路复用

什么是多路复用技术呢? 多路复用(multiplexing),简称复用,是通信技术中的基本概念 。 事实上,多路复用技术的原理就是,把通信资源或者说是链路、信道资源进行的划分,分成一系列的资源片。把这些资源片分配…

一、多路复用

1.什么是多路复用 数据通信系统或计算机网络系统中,传输媒体的带宽或容量往往会大于传输单一信号的需求,为了有效地利用通信线路,希望一个信道同时传输多路信号,这就是所谓的多路复用技术(Multiplexing)。采用多路复用技术能把多个信号组合起…

分类变量回归: R语言中哑变量编码本质

本篇描述分类变量如何进行回归(翻译自http://www.sthda.com/english/articles/40-regression-analysis/163-regression-with-categorical-variables-dummy-coding-essentials-in-r/) 分类变量(也称为因子或定性变量)是可以将观测数据分组的变量。它们有…

python哑变量转换为类别变量

就是get_dummies()功能的逆变化,把哑变量重新变为类别变量 原先的数据 转变后的数据 代码如下: df.columns[1,2,3,4,5,6]df df[df1].stack().reset_index() df.columns[A,B,C] print(df) del df[A] del df[C]

回归模型中的哑变量

在构建回归模型时,如果自变量X为连续性变量,回归系数β可以解释为:在其他自变量不变的条件下,X每改变一个单位,所引起的因变量Y的平均变化量;如果自变量X为二分类变量,例如是否饮酒(…

Python超实用小技巧:分类变量转化为哑变量(附哑变量详解)

代码示例 features ["Pclass", "Sex", "SibSp", "Parch"]# 筛选出分类变量用来建模X pd.get_dummies(train[features])# 把分类变量转化为哑变量 哑变量详解 定义:哑变量(DummyVariable)&#xf…

多元线性回归哑变量设置方法

多元线性回归是研究一个连续型变量和其他多个变量间线性关系的统计学分析方法,如果在自变量中存在分类变量,如果直接将分类变量和连续性变量统一纳入模型进行分析是有问题的,尤其是无序分类资料,即使进入了模型,也难以…

matlab虚拟变量,不要再稀里糊涂的做回归了:如何设置哑变量

原标题:不要再稀里糊涂的做回归了:如何设置哑变量 虚拟变量 ( Dummy Variables) 又称虚设变量、名义变量或哑变量,用以反映质的属性的一个人工变量,是量化了的自变量,通常取值为0或1。引入哑变量可使线形回归模型变得更…

哑变量与逻辑回归

哑变量与逻辑回归 数据 部分数据: admit,gre,gpa,rank 0,380,3.61,3 1,660,3.67,3 1,800,4,1 1,640,3.19,4 0,520,2.93,4 1,760,3,2 1,560,2.98,1 0,400,3.08,2 1,540,3.39,3 0,700,3.92,2 0,800,4,4 0,440,3.22,1 1,760,4,1 0,700,3.08,2 1,700,4,1导入库 numpy…

哑变量处理

dummyVars(formula, data, sep “.”, levelsOnly FALSE, fullRank FALSE, …) sep:因子变量名及其级别之间的可选分隔符。使用sep NULL表示没有分隔符(即模型的正常行为)。 data4 <- read.csv("玩家玩牌数据.csv") head(data4) library(VIM) aggr(data4,pro…

哑变量的基本介绍及R语言设置

哑变量的基本介绍及R语言设置 1. 哑变量的基本介绍【摘自医咖会】1.1 什么是哑变量&#xff1f;1.2 什么情况下需要设置哑变量?1.3 如何设置哑变量的参照组&#xff1f;1.4 设置哑变量时的注意事项 2. R语言中哑变量的设置2.1 示例数据2.2 哑变量设置的4种方式2.3 线性回归小实…

matlab如何转换哑变量,SPSS教程:手把手教你设置哑变量及解读结果!

将哑变量引入回归模型,虽然使模型变得较为复杂,但可以更直观地反映出该自变量的不同属性对于因变量的影响,提高了模型的精度和准确度。 举一个例子,如职业因素,假设分为学生、农民、工人、公务员、其他共5个分类,其中以“其他职业”作为参照,此时需要设定4个哑变量X1-X4…

clear both

<style type"text/css"> p.f1{float:left;width :100px;} p.f2{float:left;width :100px;} </style> <title>无标题文档</title> </head> <body> <p class"f1">这个是第1项 </p> <p class"f2&quo…

CSS中正确理解clear:both

原文地址&#xff1a;http://blog.sina.com.cn/s/blog_709475a10100wkdj.html 要注意以下几点&#xff1a; 1、 浮动元素会被自动设置成块级元素&#xff0c;相当于给元素设置了display:block&#xff08;块级元素能设置宽和高&#xff0c;而行内元素则不可以&#xff09;。 …

clear:both 的作用

如&#xff1a; <div style"border:2px solid red;"> <div style"float:left;width:80px;height:80px;border:1px solid blue;">TEST DIV</div> <div style"clear:both;"></div> </div> 你可以将此部分代码…

CSS中clear:both的作用

clear:both意思就是清除浮动&#xff0c;例如我们设置了三个div如下&#xff1a; <div style"line-height: 30px;background-color: #EEEEEE;height: 100px;width: 50px;float: left;padding: 5px;">侧边栏<br>侧边栏 </div> <div style"…