当前位置: 首页 > news >正文

Nginx 是如何解决惊群效应的?

什么是惊群效应?

第一次听到的这个名词的时候觉得很是有趣,不知道是个什么意思,总觉得又是奇怪的中文翻译导致的。

复杂的说(来源于网络)TLDR;

惊群效应(thundering herd)是指多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终却只能有一个进程(线程)获得这个时间的“控制权”,对该事件进行处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群效应。

简单的讲(我的大白话)

有一道雷打下来,把很多人都吵醒了,但只有其中一个人去收衣服了。也就是:有一个请求过来了,把很多进程都唤醒了,但只有其中一个能最终处理。

原因&问题

说起来其实也简单,多数时候为了提高应用的请求处理能力,会使用多进程(多线程)去监听请求,当请求来时,因为都有能力处理,所以就都被唤醒了。

而问题就是,最终还是只能有一个进程能来处理。当请求多了,不停地唤醒、休眠、唤醒、休眠,做了很多的无用功,上下文切换又累,对吧。那怎么解决这个问题呢?下面就是今天要看的重点,我们看看 nginx 是如何解决这个问题的。

Nginx 架构

第一点我们需要了解 nginx 大致的架构是怎么样的。nginx 将进程分为 master 和 worker 两类,非常常见的一种 M-S 策略,也就是 master 负责统筹管理 worker,当然它也负责如:启动、读取配置文件,监听处理各种信号等工作。

但是,第一个要注意的问题就出现了,master 的工作有且只有这些,对于请求来说它是不管的,就如同图中所示,请求是直接被 worker 处理的。如此一来,请求应该被哪个 worker 处理呢?worker 内部又是如何处理请求的呢?

Nginx 使用 epoll

接下来我们就要知道 nginx 是如何使用 epoll 来处理请求的。下面可能会涉及到一些源码的内容,但不用担心,你不需要全部理解,只需要知道它们的作用就可以了。顺便我会简单描述一下我是如何去找到这些源码的位置的。

Master 的工作

其实 Master 并不是毫无作为,至少端口是它来占的。https://github.com/nginx/nginx/blob/b489ba83e9be446923facfe1a2fe392be3095d1f/src/core/ngx_connection.c#L407C13-L407C13

ngx_open_listening_sockets(ngx_cycle_t *cycle)
{.....for (i = 0; i < cycle->listening.nelts; i++) {.....if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {if (listen(s, ls[i].backlog) == -1) {
}

那么,根据我们 nginx.conf 的配置文件,看需要监听哪个端口,于是就去 bind 的了,这里没问题。

【发现源码】这里我是直接在代码里面搜 bind 方法去找的,因为我知道,不管你怎么样,你总是要绑定端口的

然后是创建 worker 的,虽不起眼,但很关键。https://github.com/nginx/nginx/blob/b489ba83e9be446923facfe1a2fe392be3095d1f/src/os/unix/ngx_process.c#L186

ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,char *name, ngx_int_t respawn)
{....pid = fork();

【发现源码】这里我直接搜 fork,整个项目里面需要 fork 的情况只有两个地方,很快就找到了 worker

由于是 fork 创建的,也就是复制了一份 task_struct 结构。所以 master 的几乎全部它都有。

Worker 的工作

Nginx 有一个分模块的思想,它将不同功能分成了不同的模块,而 epoll 自然就是在 ngx_epoll_module.c 中了

https://github.com/nginx/nginx/blob/b489ba83e9be446923facfe1a2fe392be3095d1f/src/event/modules/ngx_epoll_module.c#L330C23-L330C23

ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{ngx_epoll_conf_t  *epcf;epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);if (ep == -1) {ep = epoll_create(cycle->connection_n / 2);

其他不重要,就连 epoll_ctl 和 epoll_wait 也不重要了,这里你需要知道的就是,从调用链路来看,是 worker 创建的 epoll 对象,也就是每个 worker 都有自己的 epoll 对象,而监听的sokcet 是一样的!

【发现源码】这里更加直接,搜索 epoll_create 肯定就能找到

问题的关键

此时问题的关键基本就能了解了,每个 worker 都有处理能力,请求来了此时应该唤醒谁呢?讲道理那不是所有 epoll 都会有事件,所有 worker 都 accept 请求?显然这样是不行的。那么 nginx 是如何解决的呢?

相关视频推荐

Nginx源码解析惊群方案、惊群现象演示、锁方案讲解

16w行的nginx源码,如何才能读懂呢?全面分析nginx的机制

epoll的原理与使用,epoll比select/poll强在哪里?

Linux C/C++开发(后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全)

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

如何解决

解决方式一共有三种,下面我们一个个来看:

  1. accept_mutex(应用层的解决方案)

  2. EPOLLEXCLUSIVE(内核层的解决方案)

  3. SO_REUSEPORT(内核层的解决方案)

accept_mutex

看到 mutex 可能你就知道了,锁嘛!这也是对于高并发处理的 ”基操“ 遇事不决加锁,没错,加锁肯定能解决问题。https://github.com/nginx/nginx/blob/b489ba83e9be446923facfe1a2fe392be3095d1f/src/event/ngx_event_accept.c#L328

具体代码就不展示了,其中细节很多,但本质很容易理解,就是当请求来了,谁拿到了这个锁,谁就去处理。没拿到的就不管了。锁的问题很直接,除了慢没啥不好的,但至少很公平。

EPOLLEXCLUSIVE

EPOLLEXCLUSIVE 是 2016 年 4.5+ 内核新添加的一个 epoll 的标识。它降低了多个进程/线程通过 epoll_ctl 添加共享 fd 引发的惊群概率,使得一个事件发生时,只唤醒一个正在 epoll_wait 阻塞等待唤醒的进程(而不是全部唤醒)。

关键是:每次内核只唤醒一个睡眠的进程处理资源

但,这个方案不是完美的解决了,它仅是降低了概率哦。为什么这样说呢?相比于原来全部唤醒,那肯定是好了不少,降低了冲突。但由于本质来说 socket 是共享的,当前进程处理完成的时间不确定,在后面被唤醒的进程可能会发现当前的 socket 已经被之前唤醒的进程处理掉了。

SO_REUSEPORT

Nginx 在 1.9.1 版本加入了这个功能 https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/

其本质是利用了 Linux 的 reuseport 的特性,使用 reuseport 内核允许多个进程 listening socket 到同一个端口上,而从内核层面做了负载均衡,每次唤醒其中一个进程。

反应到 Nginx 上就是,每个 Worker 进程都创建独立的 listening socket,监听相同的端口,accept 时只有一个进程会获得连接。效果就和下图所示一样。

而使用方式则是:

http {server {listen 80 reuseport;server_name  localhost;# ...}
}

从官方的测试情况来看确实是厉害

当然,正所谓:完事无绝对,技术无银弹。这个方案的问题在于内核是不知道你忙还是不忙的。只会无脑的丢给你。与之前的抢锁对比,抢锁的进程一定是不忙的,现在手上的工作都已经忙不过来了,没机会去抢锁了;而这个方案可能导致,如果当前进程忙不过来了,还是会只要根据 reuseport 的负载规则轮到你了就会发送给你,所以会导致有的请求被前面慢的请求卡住了。

总结

本文,从了解什么 ”惊群效应“ 到 nginx 架构和 epoll 处理的原理,最终分析三种不同的处理 “惊群效应” 的方案。分析到这里,我想你应该明白其实 nginx 这个多队列服务模型是所存在的一些问题,只不过绝大多数场景已经完完全全够用了。

相关文章:

Nginx 是如何解决惊群效应的?

什么是惊群效应&#xff1f; 第一次听到的这个名词的时候觉得很是有趣&#xff0c;不知道是个什么意思&#xff0c;总觉得又是奇怪的中文翻译导致的。 复杂的说&#xff08;来源于网络&#xff09;TLDR; 惊群效应&#xff08;thundering herd&#xff09;是指多进程&#xff…...

【深度学习实验】网络优化与正则化(三):随机梯度下降的改进——Adam算法详解(Adam≈梯度方向优化Momentum+自适应学习率RMSprop)

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入必要的库1. 随机梯度下降SGD算法a. PyTorch中的SGD优化器b. 使用SGD优化器的前馈神经网络 2.随机梯度下降的改进方法a. 学习率调整b. 梯度估计修正 3. 梯度估计修正&#xff1a;动量法Momen…...

如何解决网页中的pdf文件无法下载?pdf打印显示空白怎么办?

问题描述 偶然间&#xff0c;遇到这样一个问题&#xff0c;一个网页上的附件pdf想要下载打印下来&#xff0c;奈何尝试多种办法都不能将其下载下载&#xff0c;点击打印出现的也是一片空白 百度搜索了一些解决方案都不太行&#xff0c;主要解决方案如&#xff1a;https://zh…...

【JVM】类加载器 Bootstrap、Extension、Application、User Define 以及 双亲委派

以下环境为 jdk1.8 两大类 分类成员语言继承关系引导类加载器bootstrap 引导类加载器C/C无自定义类加载器extension 拓展类加载器、application 系统/应用类加载器、user define 用户自定义类加载器Java继承于 java.lang.ClassLoader 四小类 Bootstrap 引导类加载器 负责加…...

读书笔记:彼得·德鲁克《认识管理》第15章 使工作富有成效:工作和过程

一、章节内容概述 不同员工在技术熟练程度、知识掌握程度方面有所不同&#xff0c;但所有工 作本质上都是相同的&#xff0c;为了实现富有成效&#xff0c;需要遵循同样的步骤&#xff0c;划分 为同样的阶段&#xff0c;受到同样的对待&#xff0c;需要分析、综合、控制以及相…...

媒体软文投放的流程与媒体平台的选择

海内外媒体软文&#xff1a;助力信息传播与品牌建设 在当今数字化时代&#xff0c;企业如何在庞大的信息海洋中脱颖而出&#xff0c;成为品牌建设的领军者&#xff1f;媒体软文投放无疑是一项强大的策略&#xff0c;通过选择合适的平台&#xff0c;精准投放&#xff0c;可以实…...

【excel技巧】如何取消excel隐藏?

Excel工作表中的行列隐藏了数据&#xff0c;如何取消隐藏行列呢&#xff1f;今天分享几个方法给大家 方法一&#xff1a; 选中隐藏的区域&#xff0c;点击右键&#xff0c;选择【取消隐藏】就可以了 方法二&#xff1a; 如果工作表中有多个地方有隐藏的话&#xff0c;还是建…...

AIGC专栏8——EasyPhoto 视频领域拓展-让AIGC肖像动起来

AIGC专栏8——EasyPhoto 视频领域初拓展-让AIGC肖像动起来 学习前言源码下载地址技术原理储备Video Inference 功能说明 & 效果展示1、Text2Video功能说明a、实现原理简介b、文到视频UI介绍c、结果展示 2、Image2Video功能说明a、实现原理简介i、单图模式ii、首尾图模式 b、…...

C++ RBTree 理论

目录 这个性质可以总结为 红黑树的最短最长路径 红黑树的路径范围 code 结构 搞颜色 类 插入 插入逻辑 新插入节点 思考&#xff1a;2. 检测新节点插入后&#xff0c;红黑树的性质是否造到破坏&#xff1f; 解决方法 变色 旋转变色 第三种情况&#xff0c;如果根…...

制作这种在线宣传画册,可轻松收获客户!

制作企业宣传画册&#xff0c;首先要了解企业制作宣传画册的需求以及展示方向&#xff0c;如今互联网时代&#xff0c;宣传画册的制作也应该要创新&#xff0c;而制作一本在线电子宣传画册用于线上宣传是非常有必要的。如何制作呢&#xff1f; 我们 可以使用FLBOOK平台在线制作…...

数据结构 | 图

最小生成树算法 Prime算法 算法思路&#xff1a;从已选顶点所关联的未选边中找出权重最小的边&#xff0c;并且生成树不存在环。 其中&#xff0c;已选顶点是构成最小生成树的结点&#xff0c;未选边是不属于生成树中的边。 例子&#xff1a; 第一步&#xff1a; 假设我们从顶…...

[文件读取]shopxo 文件读取(CNVD-2021-15822)

1.1漏洞描述 漏洞编号CNVD-2021-15822漏洞类型文件读取漏洞等级⭐⭐漏洞环境VULFOCUS攻击方式 描述: ShopXO是一套开源的企业级开源电子商务系统。 ShopXO存在任意文件读取漏洞&#xff0c;攻击者可利用该漏洞获取敏感信息。 1.2漏洞等级 高危 1.3影响版本 ShopXO 1.4漏洞复现…...

zookeeper应用之分布式锁

在分布式系统中多个服务需要竞争同一个资源时就需要分布式锁&#xff0c;这里使用zookeeper的临时顺序节点来实现分布式锁。 在节点X下创建临时顺序节点&#xff0c;getChildren()获取节点X的所有子节点&#xff0c;判断当前节点是否是第一个子节点&#xff0c;如果是就获取锁…...

20. 机器学习——PCA 与 LDA

机器学习面试题汇总与解析——PCA 与 LDA 本章讲解知识点 什么是数据降维PCA本专栏适合于Python已经入门的学生或人士,有一定的编程基础。 本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。 本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是一…...

深度学习准召

准确率&#xff08;Precision&#xff09;和召回率&#xff08;Recall&#xff09;是两个用来评价一个模型的好坏的指标&#xff0c;它们有不同的意义&#xff1a; 准确率&#xff08;Precision&#xff09;&#xff1a;准确率是在所有被模型判断为正例的样本中&#xff0c;有…...

AtCoder ABC154

C - Distinct or Not 签到题&#xff0c;注意大小写和以前的不一样 D - Dice in Line 签到题2&#xff0c;用个窗口即可 E - Almost Everywhere Zero 数位DP&#xff08;搜索&#xff09;的例题 pos表示当前搜索到的位置&#xff08;开始为0&#xff0c;结束为n&#xff09; …...

可以非常明显地感受到,一场有关直播带货的暗流正在涌动

虽然有关直播带货的争论依然还在持续&#xff0c;但是&#xff0c;我们依然无法否认今年的双十一依然是直播带货的高光时刻。无论是以淘宝、京东和拼多多为代表的传统电商平台&#xff0c;还是以抖音、快手为代表的新电商平台&#xff0c;几乎都将今年双十一的重心放在了直播带…...

C++中的四种构造函数

在C中&#xff0c;有几种不同类型的构造函数&#xff0c;基于它们的特性和用途&#xff0c;可以将它们分类为以下四种&#xff1a; 默认构造函数&#xff08;Default Constructor&#xff09;: 如果没有为类定义任何构造函数&#xff0c;编译器将为其提供一个默认构造函数。这种…...

通过反射获取某个对象属性是否存在,并获取对象值

SneakyThrowspublic static void main(String[] args) {User user new User("张三", 10);// 获取指定属性名的值String propertyName "name2";Field[] fields user.getClass().getDeclaredFields();// 输出属性名Boolean flag false;for (Field field …...

【MySQL】存储过程与函数

一、存储过程 1、什么是存储过程 它是一组经过预先编译的SQL的封装它被存储在MySQL服务器上&#xff0c;当需要执行它时&#xff0c;客户端只需要向服务器发出调用命令&#xff0c;就可以把这一系列预先存储好的SQL语句全部执行 2、存储过程的优缺点 优点 简化操作&#xf…...

UOS系统下WPS卸载不干净?手把手教你用命令行精准清理(附dpkg/apt组合拳)

UOS系统下WPS卸载不干净&#xff1f;手把手教你用命令行精准清理 在UOS系统日常使用中&#xff0c;WPS Office作为常用办公软件&#xff0c;有时因版本更新或功能调整需要彻底卸载。但不少用户发现&#xff0c;通过图形界面或简单命令卸载后&#xff0c;系统中仍残留配置文件、…...

sudo企业级应用【20260525】001篇

文章目录 一、总体设计思路 1️⃣ 设计原则 2️⃣ 日志策略(重点) 二、10 个真实生产场景(含 sudoers 配置) 🔹 Linux 系统管理(3 个) ✅ 场景 1:基础运维(用户 / 权限) ✅ 场景 2:磁盘与文件系统 ✅ 场景 3:网络与防火墙 🔹 云管理(2 个) ✅ 场景 4:云 CLI …...

PlayAI语音合成质量到底如何?12款竞品横向对比+5项MOS/LSD/STOI硬指标揭榜

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;PlayAI语音合成质量评测报告 PlayAI 是一款面向开发者与内容创作者的实时语音合成&#xff08;TTS&#xff09;服务&#xff0c;支持多语种、多音色及情感可控输出。本报告基于客观可复现的评测流程&#xff0…...

Linux服务器被挖矿木马劫持的五步应急处置指南

1. 这不是“中病毒”&#xff0c;是服务器被劫持成了矿机——先别慌&#xff0c;但必须立刻断网“服务器被黑客攻击&#xff0c;用来挖矿&#xff01;”——这句话在运维圈里一出&#xff0c;比收到OOM告警还让人头皮发紧。它不像网页被挂马、数据库被拖库那样有明显业务影响&a…...

基于树莓派打造万能遥控器:从硬件选型到Web控制界面全解析

1. 项目概述&#xff1a;打造一个能“学习”的万能遥控器家里遥控器越来越多&#xff0c;电视、空调、风扇、灯带……每个设备都配一个&#xff0c;找起来麻烦&#xff0c;用起来也乱。市面上所谓的“万能遥控器”其实并不万能&#xff0c;它内置的码库有限&#xff0c;很多小众…...

别再瞎拖拽了!Unity Prefab从创建到批量修改的保姆级工作流(含变体与嵌套实战)

Unity Prefab高效工作流&#xff1a;从创建到批量修改的实战指南在Unity项目开发中&#xff0c;Prefab&#xff08;预制体&#xff09;是最基础也最强大的工具之一。但很多开发者&#xff0c;尤其是初学者&#xff0c;往往停留在简单的"拖拽-修改"阶段&#xff0c;没…...

XZ6128A工作电压5-100V 输出电流5A 升压型大功率LED灯恒流驱动控制芯片

概述 XZ6128A是一款高效率、高精度的升压型大功率LED灯恒流驱动控制芯片。 XZ6128A内置高精度误差放大器&#xff0c;固定关断时间控制电路&#xff0c;恒流驱动电路等&#xff0c;特别适合大功率、多个高亮度LED灯串的恒流驱动。 XZ6128A采用固定关断时间的控制方式&#xff0…...

人工智能的伦理与安全:这3个问题,软件测试从业者必须重视

随着大语言模型、生成式AI的爆发式落地&#xff0c;人工智能已经从实验室走向千行百业的生产场景&#xff0c;深刻改变着软件开发与交付的逻辑。对于直接把控产品质量关口的软件测试从业者来说&#xff0c;我们的职责早已不再是单纯验证功能可用性、排查性能bug那么简单——AI系…...

DLA功耗优化验证:tegrastats实战指南

重磅预告&#xff1a;本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容&#xff0c;该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著&#xff0c;特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…...

机器学习赋能矩方法:破解稀薄气体强非平衡流动模拟难题

1. 项目概述&#xff1a;当矩方法遇见机器学习在计算流体力学领域&#xff0c;模拟稀薄气体动力学和强非平衡流动&#xff0c;一直是个让工程师和科学家们头疼的“硬骨头”。想象一下&#xff0c;你正在设计一架高超音速飞行器&#xff0c;当它以数倍音速在大气层边缘飞行时&am…...