Nginx中的惊群现象解决方法

*什么是惊群现象?Nginx中用了什么方法来避免这种问题的发生?本篇就解决这两个问题。。。→_→*

  1. 惊群现象的定义与危害

    • 在Nginx中,每一个worker进程都是由master进程fork出来的。master进程创建socket后进行listen、bind操作,fork出来的worker继承了socket,调用accpet开始监听等待网络连接
    • 如果这时有多个worker进程都在等待事件的发生。当事件发生时,这些worker进程被同时唤醒,但最终只有一个worker进程可以处理事件成功,其他的worker进程就会重新进入阻塞状态
    • 当惊群现象发生时,内核会依次唤醒所有的worker进程,这种操作会导致系统在瞬时占用极大的资源,但最后却只有一个worker进程处理事件成功,这就造成了极大的资源浪费
  2. Nginx中解决惊群现象的方法
    • Nginx中规定同一时刻只能有唯一一个的worker进程监听Web端口,这样就不会发生惊群了,此时新连接事件只能唤醒唯一正在监听端口的worker进程
  3. 源码剖析
ngx_int_t
ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
{
    //使用worker进程间同步锁——ngx_accept_mutex,ngx_shmtx_trylock返回1表示成功获取锁,返回0表示获取锁失败。ngx_shmtx_trylock是非阻塞的,如果此时ngx_accept_mutex被其他worker进程占有,那么ngx_shmtx_trylock会立即返回
    if (ngx_shmtx_trylock(&ngx_accept_mutex)) {

        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "accept mutex locked");

        //ngx_accept_mutex_held为1时表示当前worker进程已经获取到了锁,那么就立即返回
        if (ngx_accept_mutex_held
            && ngx_accept_events == 0
            && !(ngx_event_flags & NGX_USE_RTSIG_EVENT))
        {
            return NGX_OK;
        }

        //将所有监听连接的读事件添加到当前的epoll等事件驱动模块中
        if (ngx_enable_accept_events(cycle) == NGX_ERROR) {
            //如果将所有监听连接的读事件添加到当前的epoll等事件驱动模块中失败,那么就必须释放ngx_accept_mutex锁
            ngx_shmtx_unlock(&ngx_accept_mutex);
            return NGX_ERROR;
        }

        //此时需要把ngx_accept_mutex_held置为1,方便本进程的其他驱动模块它已经获取到了锁
        ngx_accept_events = 0;
        ngx_accept_mutex_held = 1;

        return NGX_OK;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "accept mutex lock failed: %ui", ngx_accept_mutex_held);

    //此时ngx_shmtx_trylock返回了0,表示获取ngx_shmtx_trylock锁失败。但是此时ngx_accept_mutex_held还为1,即当前worker进程还在占有ngx_accept_mutex锁,就说明有问题
    if (ngx_accept_mutex_held) {
        //将所有监听连接的读事件从事件模块中移出
        if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
            return NGX_ERROR;
        }
        //没有获取到ngx_accept_mutex锁时,将ngx_accept_mutex_held置为0
        ngx_accept_mutex_held = 0;
    }

    return NGX_OK;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

*本篇只分析了Nginx中如何保证不发生惊群现象的解决方法,后面其实还有worker进程何时释放ngx_accept_mutex锁的问题。。其超出了本篇的范围。。。就不在这里继续讨论了。。明天加油。。。→_→*

原文地址:https://www.cnblogs.com/zhoading/p/9678126.html

时间: 2024-12-17 00:24:54

Nginx中的惊群现象解决方法的相关文章

Nginx如何解决“惊群”现象

首先解释下什么是"惊群"现象:如果多个工作进程同时拥有某个监听套接口,那么一旦该套接口出现某客户端请求,此时就将引发所有拥有该套接口的工作进程去争抢这个请求,能争抢到的肯定只有某一个工作进程,而其他工作进程注定要无功而返,这种现象即为"惊群". Nginx解决这种"惊群"现象使用的是负载均衡的策略,接下来先结合Nginx的源码详细介绍下Nginx的这种负载均衡策略. 首先是Nginx如何开启负载均衡策略:当然运行的Nginx要是多进程模型,并且工

Nginx——事件驱动机制(惊群问题,负载均衡)

事件框架处理流程 每个worker子进程都在ngx_worker_process_cycle方法中循环处理事件,处理分发事件则在ngx_worker_process_cycle方法中调用ngx_process_events_and_timers方法,循环调用该方法就是 在处理所有事件,这正是事件驱动机制的核心.该方法既会处理普通的网络事件,也会处理定时器事件. ngx_process_events_and_timers方法中核心操作主要有以下3个: 1)  调用所使用事件驱动模块实现的proce

epoll惊群问题-解决思路

[遇到问题] 手头原来有一个单进程的linux epoll服务器程序,近来希望将它改写成多进程版本,主要原因有: 在服务高峰期间 并发的 网络请求非常海量,目前的单进程版本的程序有点吃不消:单进程时只有一个循环先后处理epoll_wait()到的事件,使得某些不幸排队靠后的socket fd的网络事件处理不及时(担心有些socket客户端等不耐烦而超时断开): 希望充分利用到服务器的多颗CPU: 但随着改写工作的深入,便第一次碰到了“惊群”问题,一开始我的程序设想如下: 主进程先监听端口, li

Redis 利用锁机制来防止缓存过期产生的惊群现象-转载自 http://my.oschina.net/u/1156660/blog/360552

首先,所谓的缓存过期引起的“惊群”现象是指,在大并发情况下,我们通常会用缓存来给数据库分压,但是会有这么一种情况发生,那就是在一定时间 内生成大量的缓存,然后当缓存到期之后又有大量的缓存失效,导致后端数据库的压力突然增大,这种现象就可以称为“缓存过期产生的惊群现象”! 以下代码的思路,就是利用“锁机制”来防止惊群现象.先看代码: class KomaRedis{ private $redis; //redis对象 private static $_instance = null; private

Nginx常见错误与问题之解决方法技术指南

  Nginx常见错误与问题之解决方法技术指南. 安装环境: 系统环境:redhat enterprise 6.5 64bit 1.Nginx 常见启动错误 有的时候初次安装nginx的时候会报这样的错误 sbin/nginx -c conf/nginx.conf 报错内容:sbin/nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or

在沙箱中IE不能上网的解决方法

最近在解决一个问题,在我们的沙箱中IE不能上网 现象: IE不能上网,输入www.baidu.com 提示:不能查找到DNS.也不能ping 通 其他浏览器上网没有问题(SG浏览器,Chrome ,firefox,猎豹,360) 为什么IE不能上网呢? 解决: 在应用层挂调试IE,在ws2_32!socket 下断点,发现 socket 不能创建成功.然后发现首先需要访问 qurl.f.360.cn ,然后再访问www.baidu.com 那么难道我访问网址需要经过qurl.f.360.cn过滤

pthread_cond_signal惊群现象

1.如下代码所示: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> pthread_mutex_t count_lock; pthread_cond_t count_ready; int count; void *decrement_count(void *arg) { while(1) { pthread_mutex_lock(&coun

nginx 502 bad故障原因及解决方法收集

如题,最近网站频繁出现502错误,简直无法正常运转,出现这种情况大多是php-cgi超时没有返回信息,或进程僵死等情况造成的.我们的nginx已经配置到极致这些都已经老早做过修改了,但现在又出然出现. 经过分析将nginx的error log打开,发现”pstream sent too big header while reading response header from upstream”这样的错误提示,查阅了一下资料,大意是nginx缓冲区有一个bug造成的,我们网站的页面消耗占用缓冲区

Eclipse ADT中的logcat不显示解决方法

Eclipse ADT中的logcat不显示解决方法: 1.在Eclipse界面中找到DDMS,然后找到device选项卡,在这个选项卡中选择reset adb,如果不行尝试方法2: 2.不用关闭eclipse和模拟器,在Android SDK的tools目录下有个 ddms.bat 批处理文件,运行这个文件可以启动DDMS,同时这里面有logcat,可以显示信息: 3.以上方法都不行,最终杀手锏就是重启eclipse,重启模拟器,记得在任务管理器中关闭adb.exe,这时应该就可以了. 4.用