nginx中的epoll模型
要了解epoll模型,就要一个一个知识点由浅至深地去探索。
1.IO复用技术
IO流请求操作系统内核,有串行处理和并行处理两种概念。
串行处理是前面一个操作处理地时候,后面的所有操作都需要等待。因此,必须考虑以并行处理的方式来完成整个IO流的请求,实现最大的并发和吞吐。这里就用到了IO复用技术。
IO复用技术就是让一个Socket来做复用完成整个IO流的请求。实现IO流的请求其中一种方式就是多线程,但是多线程会占用大量资源,不便于管理,因此又出现了IO多路复用技术。
2.IO多路复用技术
IO多路复用是指多个描述符的I/O操作都能在一个线程内并发交替地顺序完成,这里的复用指的是复用同一个线程。
对操作系统内核而言,多路复用其实是要完成操作系统IO的请求,对于IO文件的请求,当一个IO流要进行对应的文件处理的时候,要获取一组文件的描述符,当文件描述符还没就绪的时候,它就一直在等待,直到描述符就绪,就马上上报系统的一个通知的机制,以此来告诉主应用程序它已经准备就绪了,你可以来操作了。这种方式就是IO多路复用方式。
3.IO多路复用技术的实现
IO多路复用技术的实现方式有select、poll和epoll,它们都是linux内核下的常见多路复用模型。
其中最早出现的是select模型。
4.select模型
多路复用其实就是内核态对IO请求的时候,会主动地发送所需要处理的文件对象就绪时文件的就绪信息给应用端,应用端在FD(File Description)没有就绪之前都是block,也就是阻塞对应的Socket请求,也会维护一个FD的列表。当内核态发送可用的信息,FD就绪之后,应用端采用select这种模式,会一直在遍历所维护的FD文件描述符的列表,以等到唤醒对应的线程完成对应的数据拷贝。select模型能够监视文件描述符的数量存在最大限制,且在整个过程中,select模型采用的是线性遍历的模式,这种模式效率低下。
5.epoll模型
epoll模型优化和完善了select模式的缺点,每当FD就绪,采用系统的回调函数直接将FD放入,效率高,无监视文件描述符的数量限制。
6.epoll模型的原理
设想一个场景:有100万用户同时与一个进程保持着TCP连接,而每一时刻只有几十个或几百个TCP连接是活跃的(接收到TCP包),也就是说,在每一时刻,进程只需要处理这100万个连接中的一小部分连接。那么,如何才能高效地处理这种场景呢?进程是否在每次询问操作系统收集有事件发生的TCP连接时,把这100万个连接告诉操作系统,然后由操作系统找出其中有事件发生的几百个连接呢?实际上,在Linux内核2.4版本之前,select或poll事件驱动模型就是这样处理的。
这里有个非常明显的问题,即在某一时刻,进程收集有事件的连接时,其实这100万连接中的大部分是没有事件发生的。因此,如果每次收集事件时,都把这100万连接的套接字传给操作系统(这首先就是用户态内存到内核态内存的大量复制),而由操作系统内核寻找这些连接上有没有未处理的事件,将会是巨大的资源浪费,然而select和poll就是这样做的,因此它们最多只能处理几千个并发连接。
而epoll就厉害了,它会在Linux内核中申请一个简易的文件系统,把原先的一个select或poll调用分成了3个部分:
1.调用epoll_create创建一个epoll对象(在epoll文件系统中给这个句柄分配资源,一棵红黑树和一个准备就绪list链表)。
2.调用epoll_ctl向epoll对象中添加这100万个连接的套接字。就是把socket放到红黑树上,给内核中断处理程序注册一个回调函数,然后告诉内核如果这个句柄的中断到了,就把这个socket放到准备就绪list链表里。
3.调用epoll_wait收集发生事件的TCP连接。到准备就绪list链表中处理socket,并把数据返回给用户。
这样,只需要在进程启动的时候建立1个epoll对象,并在需要的时候向它添加或删除连接即可。因此在实际收集事件时,epoll_wait的效率会非常高,因为调用epoll_wait时并没有向它传递这100万个连接,内核也不需要去遍历所有的连接,只需要到就绪list链表中去处理socket就行了。
"曾经以为拥有一点点可能的人,终究还是不可能。"
推荐阅读
-
ICCV 2023 | 关于图像复原任务中的扩散模型扩散的论文:超分割、复原、增强、去模糊、去阴影
-
问 在连体架构中,梯度如何飞回网络?即使使用不同的模型,所有 CNN 模型的权重也是相同的。
-
模型在执行路径过程中的三.js 动画(tween.js)
-
当模型范围中的模型使用管道速度太慢时,如何提高推理速度?
-
正负偏差变量 即 d2+、d2- 分别表示决策值中超出和未达到目标值的部分。而 di+、di- 均大于 0 刚性约束和目标约束(柔性目标约束有偏差) 在多目标规划中,>=/<= 在刚性约束中保持不变。当需要将约束条件转换为柔性约束条件时,需要将 >=/<= 更改为 =(因为已经有 d2+、d2- 用来表示正负偏差),并附加上 (+dii-di+) 注意这里是 +di、-di+!之所以是 +di,-di+,是因为需要将目标还原为最接近的原始刚性约束条件 优先级因素和权重因素 对多个目标进行优先排序和优先排序 目标规划的目标函数 是所有偏差变量的加权和。值得注意的是,这个加权和都取最小值。而 di+ 和 dii- 并不一定要出现在每个不同的需求层次中。具体分析需要具体问题具体分析 下面是一个例子: 题目中说设备 B 既要求充分利用,又要求尽可能不加班,那么列出的时间计量表达式即为:min z = P3 (d3- + d3 +) 使用 + 而不是 -d3 + 的原因是:正负偏差不可能同时存在,必须有 di+di=0 (因为判定值不可能同时大于目标值和小于目标值),而前面是 min,所以只要取 + 并让 di+ 和 dii- 都为正值即可。因此,得出以下规则: 最后,给出示例和相应的解法: 问题:某企业生产 A 和 B 两种产品,需要使用 A、B、C 三种设备。下表显示了与工时和设备使用限制有关的产品利润率。问该企业应如何组织生产以实现下列目标? (1) 力争利润目标不低于 1 500 美元; (2) 考虑到市场需求,A、B 两种产品的生产比例应尽量保持在 1:2; (3)设备 A 是贵重设备,严禁超时使用; (4)设备 C 可以适当加班,但要控制;设备 B 要求充分利用,但尽量不加班。 从重要性来看,设备 B 的重要性是设备 C 的三倍。 建立相应的目标规划模型并求解。 解:设企业生产 A、B 两种产品的件数分别为 x1、x2,并建立相应的目标计划模型: 以下为顺序求解法,利用 LINGO 求解: 1 级目标: 模型。 设置。 variable/1..2/:x;! s_con_num/1...4/:g,dplus,dminus;!所需软约束数量(g=dplus=dminus 数量)及相关参数; s_con(s_con_num);! s_con(s_con_num,variable):c;!软约束系数; 结束集 数据。 g=1500 0 16 15. c=200 300 2 -1 4 0 0 5; 结束数据 min=dminus(1);!第一个目标函数;!对应于 min=z 的第一小部分;! 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); !使用设置完成的数据构建软约束表达式; ! !软约束表达式 @for(variable:@gin(x)); !将变量约束为整数; ! 结束 此时,第一级目标的最优值为 0,第一级偏差为 0: 第二级目标: !求 dminus(1)=0,然后求解第二级目标。 模型。 设置。 变量/1..2/:x;!设置:变量/1..2/:x; ! s_con_num/1...4/:g,dplus,dminus;!软约束数量及相关参数; s_con(s_con_num(s_con_num));! s_con(s_con_num,variable):c;! 软约束系数; s_con(s_con_num,variable):c;! 结束集 数据。 g=1500 0 16 15; c=200 300 2 -1 4 0 0 5; 结束数据 min=dminus(2)+dplus(2);!第二个目标函数 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); ! 软约束表达式;! dminus(1)=0; !第一个目标结果 @for(variable:@gin(x)); ! 结束 此时,第二个目标的最优值为 0,偏差为 0: 第三目标 !求 dminus(2)=0,然后求解第三个目标。 模型。 设置。 变量/1..2/:x;!设置:变量/1..2/:x; ! s_con_num/1...4/:g,dplus,dminus;!软约束数量及相关参数; s_con(s_con_num(s_con_num));! s_con(s_con_num,variable):c;! 软约束系数; s_con(s_con_num,variable):c;! 结束集 数据。 g=1500 0 16 15; c=200 300 2 -1 4 0 0 5; 结束数据 min=3*dminus(3)+3*dplus(3)+dminus(4);!第三个目标函数。 2*x(1)+2*x(2)<12;!硬约束 @for(s_con_num(i):@sum(variable(j):c(i,j)*x(j))+dminus(i)-dplus(i)=g(i)); ! 软约束表达式;! dminus(1)=0; !第一个目标约束条件; ! dminus(2)+dplus(2)=0; !第二个目标约束条件 @for(variable:@gin(x));! 结束 最终结果为 x1=2,x2=4,dplus(1)=100,最优利润为
-
在大型语言模型的微调过程中,RLHF 和 RLAIF 有什么区别?
-
在 python Django 中向用户分配库存包括定义库存模型、用户模型和分配库存的逻辑。
-
kqueue 和 epoll 的高级 IO 模型
-
从 epoll 入门到 redis 中的 epoll
-
nginx中的epoll模型