高并发中的惊群问题

2023-11-10

目录

1 惊群效应是什么?

2 惊群效应消耗了什么

3 惊群的几种情况

3.1 accept惊群(新版内核已解决) 

3.2 epoll_create 在 fork 之前创建

3.3 epoll_create 在 fork 之后创建

4 Linux与Nginx的解决方案

4.1 锁策略

4.2 SO_REUSEPORT

4.3 EPOLLEXCLUSIVE标志位


1 惊群效应是什么?

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

惊群效应消耗了什么

  • Linux 内核对用户进程(线程)频繁地做无效的调度、上下文切换等使系统性能大打折扣。上下文切换(context switch)过高会导致 CPU 像个搬运工,频繁地在寄存器和运行队列之间奔波,更多的时间花在了进程(线程)切换,而不是在真正工作的进程(线程)上面。直接的消耗包括 CPU 寄存器要保存和加载(例如程序计数器)、系统调度器的代码需要执行。间接的消耗在于多核 cache 之间的共享数据。
  • 为了确保只有一个进程(线程)得到资源,需要对资源操作进行加锁保护,加大了系统的开销。目前一些常见的服务器软件有的是通过锁机制解决的,比如 Nginx(它的锁机制是默认开启的,可以关闭);还有些认为惊群对系统性能影响不大,没有去处理,比如 Lighttpd。

惊群的几种情况

3.1 accept惊群(新版内核已解决) 

        以多进程为例,在主进程创建监听描述符listenfd后,fork()多个子进程,多个进程共享listenfd,accept是在每个子进程中,当一个新连接来的时候,会发生惊群。

  • Linux 2.6 版本之前,监听同一个 socket 的进程会挂在同一个等待队列上,当请求到来时,会唤醒所有等待的进程。
  • Linux 2.6 版本之后,通过引入一个标记位 WQ_FLAG_EXCLUSIVE,解决掉了 accept 惊群效应。

       具体实现: 在Linux 2.6版本中,维护了一个等待队列,队列中的元素就是进程,非exclusive属性的元素会加在等待队列的前面,而exclusive属性的元素会加在等待队列的末尾,当子进程调用阻塞accept时,该进程会被打上WQ_FLAG_EXCLUSIVE标志位,从而成为exclusive属性的元素被加到等待队列中。当有TCP连接请求到达时,该等待队列会被遍历,非exclusive属性的进程会被不断地唤醒,直到出现第一个exclusive属性的进程,该进程会被唤醒,同时遍历结束。

3.2 epoll_create 在 fork 之前创建

      与 accept 惊群的原因类似,当有事件发生时,等待同一个文件描述符的所有进程(线程)都将被唤醒,而且解决思路和 accept 一致。为什么需要全部唤醒?因为内核不知道,你是否在等待文件描述符来调用 accept() 函数,还是做其他事情(信号处理,定时事件)。

       此种情况惊群效应已经被解决。、

3.3 epoll_create 在 fork 之后创建

  (1) 主进程创建listendfd

  (2) 主进程创建多个子进程

  (3)每个子进程创建自已的epollfd

  (4)每个子进程把listenfd加入到epollfd中

  (5) 当一个连接进来时,会触发epoll惊群,多个子进程epoll同时会触发

分析:

       因为每个子进程的epoll是不同的epoll, 虽然listenfd是同一个,但新连接过来时, accept会触发惊群,但内核不知道该发给哪个监听进程,因为不是同一个epoll。所以这种惊群内核并没有处理。惊群还是会出现。

       Nginx就是使用这种方式。


4 Linux与Nginx的解决方案

4.1 锁策略

基本思路是,子进程在进行epoll_ctl加入监听事件以及epoll_wait前,需要获得进程间的全局锁,获得锁的子进程才有资格通过监听获取连接请求并创建TCP连接,锁策略确保了只有1个子进程在处理TCP连接请求。

锁策略的伪代码如下:

semop(...); // lock
epoll_wait(...);
accept(...);
semop(...); // unlock
... // manage the request

Nginx在1.11.3版本(2016-07-26)之前通过配置accept_mutex默认为on支持该解决方案。

4.2 SO_REUSEPORT

       在Linux 3.9版本引入了socket套接字选项SO_REUSEPORT,Linux 3.9版本之前,一个进程通过bind一个三元组({<protocol>, <src_addr>, <src_port>})组合之后,其他进程不能再bind同样的三元组,Linux 3.9版本之后,凡是传入选项SO_REUSEPORT且为同一个用户下(安全考虑)的socket套接字都可以bind和监听同样的三元组。内核对这些监听相同三元组的socket套接字实行负载均衡,将TCP连接请求均匀地分配给这些socket套接字。

         这里的负载均衡基本原理为:当有TCP连接请求到来时,用数据包的({<src_addr>, <src_port>})作为一个hash函数的输入,将hash后的结果对SO_REUSEPORT套接字的数量取模,得到一个索引,该索引指示的数组位置对应的套接字便是要处理连接请求的套接字。

        Nginx在1.9.1版本(2015-05-26)时支持了reuseport特征,在Nginx配置中的listen指令的端口号之后增加reuseport参数后,Nginx的各个worker进程就有自己各自的监听套接字,这些监听套接字监听相同的源地址和端口号组合。

使用方式如下:

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

stream {
     server {
          listen 12345 reuseport;
          # ...
     }
}

        由于reuseport特征负载均衡在内核中的实现原理是按照套接字数量的hash,所以当Nginx进行reload,从reuseport升级为非reuseport,或者从多worker进程升级为少worker进程,都会有大幅度的性能下降。

4.3 EPOLLEXCLUSIVE标志位

        在Linux 4.5版本引入EPOLLEXCLUSIVE标志位(Linux 4.5, glibc 2.24),子进程通过调用epoll_ctl将监听套接字与监听事件加入epfd时,会同时将EPOLLEXCLUSIVE标志位显式传入,这使得子进程带上了exclusive属性,也就是互斥属性,跟Linux 2.6版本解决accept惊群效应的解决方案类似,不同的地方在于,当有监听事件发生时,唤醒的可能不止一个进程(见如下对EPOLLEXCLUSIVE标志位的官方文档说明中的“one or more”),这一定程度上缓解了惊群效应。

# http://man7.org/linux/man-pages/man2/epoll_ctl.2.html
EPOLLEXCLUSIVE (since Linux 4.5)
              Sets an exclusive wakeup mode for the epoll file descriptor
              that is being attached to the target file descriptor, fd.
              When a wakeup event occurs and multiple epoll file descriptors
              are attached to the same target file using EPOLLEXCLUSIVE, one
              or more of the epoll file descriptors will receive an event
              with epoll_wait(2).  The default in this scenario (when
              EPOLLEXCLUSIVE is not set) is for all epoll file descriptors
              to receive an event.  EPOLLEXCLUSIVE is thus useful for avoid‐
              ing thundering herd problems in certain scenarios.

Nginx在1.11.3版本时采用了该解决方案,所以从该版本开始,配置accept_mutex默认为off。

参考:

1、[框架]高并发中的惊群效应

2、Liunx与Nginx中的惊群效应

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高并发中的惊群问题 的相关文章

  • Nginx vs Apache 用于高流量站点

    Would nginx作为高流量网站的网络服务器是否是更合适的选择 我们将建立的网站是一个电子商务网站 如果这有什么不同的话 无论哪种方式 从技术角度来看 我真的对实际的 原因 感兴趣 即 为什么会nginx从技术角度来看 对于此类网站来说
  • Amazon ECS - 在 Docker 入口点上使用 IAM 角色时权限被拒绝

    我正在寻找一种将机密 证书注入 Amazon ECS 容器的方法 就我而言 它是一个简单的 nginx 容器 我一直在使用 AWS Parameter Store 关注这篇文章 https aws amazon com blogs comp
  • Docker 与 nginx 组合不断显示欢迎页面

    我是新来的docker并尝试使用最简单的 docker compose yml 显示一个 hello world 页面 并在此基础上构建最终完整的LEMP堆栈它将与我的服务器具有相同的配置 然而大多数教程已经过时 并且有很多使用方法dock
  • ./manage.py 使用 https 运行服务器

    manage py 运行服务器 0 0 0 0 8000 我使用上面的行作为我从 github 借用的代码的一部分 https github com ribeiroit boh puppet https github com ribeiro
  • 为什么 nginx 接受 Host 标头与 server_name 不匹配的请求?

    我有一个这样设置的站点 nginx 作为代理服务器 通过 UNIX 套接字代理为 Django 站点提供服务的 Gunicorn 实例的请求 这是我的 nginx 配置 server listen 80 server name api my
  • Nginx 背后的多个 Meteor 站点

    这个问题与this https stackoverflow com questions 10936242 how can i correct the meteor base url in a nginx reverse proxy conf
  • 使用 FastCGI 运行 Lua 脚本

    我目前正在尝试找出使用 FastCGI 与 lighttpd 或 Nginx 一起运行 Lua 脚本的方法 我唯一能挖到的是WSAPI http keplerproject github com wsapi 开普勒计划的一部分 但我想知道是
  • Nginx 中 uwsgi_pass 和 proxy_pass 的区别?

    我在 Nginx 后面运行 uWSGI 并一直在使用proxy pass让 Nginx 访问 uWSGI 切换到有什么好处吗uwsgi pass 如果是这样 那是什么 uwsgi pass使用一个uwsgi协议 proxy pass使用普通
  • Docker:Nginx 和 php5-fpm docker 不说话

    我想进行完全 Docker 化的 Drupal 安装 我的第一步是让容器与 Nginx 和 php5 fpm 一起运行 两者都基于 Debian 我在 CoreOS alpha 频道 使用 Digital Ocean 我的 Dockerfi
  • nginx docker 容器:502 错误网关响应

    我有一个服务监听 8080 端口 这不是一个容器 然后 我使用官方镜像创建了一个 nginx 容器 docker run name nginx d v root nginx conf etc nginx conf d p 443 443 p
  • 如何在位置中使用 Nginx Regexp

    Web 项目将静态内容放入 some content img 文件夹中 url规则为 img some md5 但文件夹中的位置 content img 前两位数字 Example url example com img fe5afe048
  • 使用 Nginx 或 Apache 来提供动态内容? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在运行 NGINX Docker 容器的 AWS EC2 上启用 HTTPS?

    我在 AWS 上有一个运行 Amazon Linux 2 的 EC2 实例 在上面 我安装了 Git docker 和 docker compose 完成后 我克隆了我的存储库并运行docker compose up让我的生产环境启动 我访
  • 找不到 NGINX brew 安装命令

    I do brew install nginx and get gt Downloading http nginx org download nginx 1 2 2 tar gz Already downloaded Library Cac
  • 常规请求期间 Django AJAX 请求未通过

    我有一个带有登录网页的 Django 站点 当提交页面上的登录表单时 它会执行登录视图 该视图会在其中运行一个需要很长时间处理 30秒左右 的函数 因此 为了在登录期间向客户端显示进度 一旦提交表单 登录页面上的 JS 函数就会开始向服务器
  • 连接到上游时 Nginx 错误:(13:权限被拒绝)

    我在我的中收到此错误nginx error log file 2014 02 17 03 42 20 crit 5455 0 1 connect to unix tmp uwsgi sock failed 13 Permission den
  • Kubernetes Ingress 在 nginx 反向代理后面运行

    我已经在可以从互联网访问的服务器上安装了 minikube 我创建了一个可用的 kubernetes 服务 gt kubectl get service myservice NAME CLUSTER IP EXTERNAL IP PORT
  • Docker 中的 NGINX 缓存 IP 地址并提供错误的 Content-Type

    Summary 我想让NGINX 不是NGINX Plus 通过使用变量从DNS名称重新解析IP地址proxy pass 如建议的这篇 Nginx 官方文章 在变量中设置域名 部分 https www nginx com blog dns
  • Nginx - Heroku Docker - 是否可以在 Heroku 上运行 Nginx 作为反向代理

    我试图弄清楚如何使用 Nginx 在 Heroku 应用程序上构建反向代理 问题是 Heroku 似乎每个应用程序只接受一个容器 但我的应用程序系统至少会使用三个容器 一个用于 Nginx 一个用于我的应用程序前端 一个用于我的业务逻辑服务
  • 阻止 ingress-nginx 负载均衡器上的特定路径

    我有许多指向入口控制器 IP 的域 我想阻止所有域 站点的 特定路径 有没有办法做到这一点 我可以用nginx ingress kubernetes io configuration snippet 对于每个站点 但正在寻找同时处理所有站点

随机推荐

  • 力扣2594.修车的最少时间

    题目描述 给你一个整数数组 ranks 表示一些机械工的 能力值 ranksi 是第 i 位机械工的能力值 能力值为 r 的机械工可以在 r n2 分钟内修好 n 辆车 同时给你一个整数 cars 表示总共需要修理的汽车数目 请你返回修理所
  • Android ApiDemos示例解析(87):Media->MediaPlayer

    本例介绍了如何使用MediaPlayer类来播放声音或是视频 涉及的Activity有三个 MediaPlayerDemo 主Activity 显示示例列表 MediaPlayerDemo Audio 子Activity 用于播放声音 在L
  • ConcurrentHashMap1.8总结

    Java8 ConcurrentHashMap结构基本上和Java8的HashMap一样 不过保证线程安全性 在JDK8中ConcurrentHashMap的结构 由于引入了红黑树 使得ConcurrentHashMap的实现非常复杂 我们
  • FPGA学习专栏-串口通信(xinlinx)

    FPGA学习专栏 串口通信 本系列文章基于开发板黑金A309 FPGA芯片为Xilinx公司的spartan6 本系列文章记录FPGA学习历程 文章目录 FPGA学习专栏 串口通信 一 串口通信原理 二 硬件设计 三 verilog代码编写
  • react之装饰器报错:This experimental syntax requires enabling one of the following parser plugin(s): “decor

    在学习mobx时 遇到了 This experimental syntax requires enabling one of the following parser plugin s decorators decorators legac
  • STM32F103ZET6【标准库函数开发】------17 DMA实验

    STM32F103ZET6有2个DMA控制器 DMA1有7个通道 DMA2有5个通道 各个通道对应的外设如下
  • Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed解决方法

    前言 Android Studio 升级到最新版本后 构建项目时 构建失败 出现错误 Caused by org codehaus groovy control MultipleCompilationErrorsException star
  • MySQL的null与not null

    相信很多用了mysql很久的人 对这两个字段属性的概念还不是很清楚 一般会有以下疑问 我字段类型是not null 为什么我可以插入空值 为毛not null的效率比null高 判断字段不为空的时候 到底要 select from tabl
  • IDEA报错:Cannot start compilation: the output path is not specified for module “testSvnKit“.Specify th

    IDEA报错Cannot start compilation the output path is not specified for module testSvnKit Specify the output path in the Pro
  • List分组的两种方式

    java8之前List分组 假设有个student类 有id name score属性 list集合中存放所有学生信息 现在要根据学生姓名进行分组 public Map
  • 精确径向基(matlab工具箱)

    原文地址 精确径向基 matlab工具箱 作者 神经网络之家 作者 梁小h 日期 2015 10 26 09 30 47 0 lt 文档仅供查阅和简单了解 深入了解请关注神经网络之家发布的 神经网络教学视频 gt 精确径向基神经网络在mat
  • HTML详解连载(5)

    HTML详解连载 5 专栏链接 link http t csdn cn xF0H3 下面进行专栏介绍 开始喽 行高 设置多行文本的间距 属性名 属性值 行高的测量方法 行高 垂直居中 技巧 字体族 属性名 属性值 示例 扩展 font 复合
  • 学期总结-2018年上

    从现在开始 我需要养成一个写作的好习惯 之所以培养这个习惯 是因为 我开始发现我的一个重大缺陷 语言表达能力的欠缺 这种能力 在一般生活中并不会有太大的作用 而且很多时候 大部分人都体会不到其所带来的 破坏 这种破坏 会让你的交际陷入阻塞
  • 不能向服务器考文件,如何往云服务器考文件

    如何往云服务器考文件 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 无法正常使用Cloud init 弹性云服务器获取M
  • 关于python爬虫逆向RPC的基础使用

    makeRequest function a b c d rpc使用的代码 function 防止重复创建websocket if window flagLX else window weiboLX makeRequest var ws n
  • egg初始化搭建swagger项目

    步骤 安装node 安装你喜欢的编辑器 初始化项目 输入安装 egg 命令 输入安装 egg dev 命令 修改 package json 基本目录结构 需手动创建 输入安装 egg sequelize 命令 数据库选择 配置 sequel
  • Android移动开发-调用摄像头进行拍照的实现

    现在Android智能手机的像素都会提供照相的功能 大部分的手机的摄像头的像素都在1000万以上的像素 有的甚至会更高 它们大多都会支持光学变焦 曝光以及快门等等 下面的程序Demo实例示范了使用Camera v2来进行拍照 当用户按下拍照
  • Windows修改MySQL数据库密码(修改或忘记密码)

    今天练习远程访问数据库时 为了方便访问 就想着把数据库密码改为统一的 以后我们也会经常遇到MySQL需要修改密码的情况 比如密码太简单 忘记密码等等 在这里我就借鉴其他人的方法总结几种修改MySQL密码的方法 我就以实际操作修改root密码
  • Android:安卓学习笔记之MVP模式的简单理解和使用

    Android MVP模式的简单理解和使用 MVP模式 1 为什么使用MVP模式 1 1 实例说明 2 一步步让你理解MVP 2 1 MVP实现第一步 将页面拆分为M V P三个模块 2 2 MVP实现第2步 使用接口通信 进一步解耦 2
  • 高并发中的惊群问题

    目录 1 惊群效应是什么 2 惊群效应消耗了什么 3 惊群的几种情况 3 1 accept惊群 新版内核已解决 3 2 epoll create 在 fork 之前创建 3 3 epoll create 在 fork 之后创建 4 Linu