zoukankan      html  css  js  c++  java
  • Nginx中的惊群现象解决方法

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

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

      • 在Nginx中,每一个worker进程都是由master进程fork出来的。master进程创建socket后进行listen、bind操作,fork出来的worker继承了socket,调用accpet开始监听等待网络连接

      • 如果这时有多个worker进程都在等待事件的发生。当事件发生时,这些worker进程被同时唤醒,但最终只有一个worker进程可以处理事件成功,其他的worker进程就会重新进入阻塞状态

      • 当惊群现象发生时,内核会依次唤醒所有的worker进程,这种操作会导致系统在瞬时占用极大的资源,但最后却只有一个worker进程处理事件成功,这就造成了极大的资源浪费

      • Nginx中的master-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锁的问题。。其超出了本篇的范围。。。就不在这里继续讨论了。。明天加油。。。→_→*

  • 相关阅读:
    又搬回来了233
    2017.10.2解题报告
    2017.10.1解题报告
    Android 百度地图开发(二)--- 定位功能之MyLocationOverlay,PopupOverlay的使用
    Last_IO_Errno: 1236 Last_IO_Error: Got fatal error 1236 from master when reading data from binary lo
    [Warning] Aborted connection 11203 to db: 'ide' user: 'nuc' host: 'prd01.mb.com' (Got an error writi
    浅析地方门户网优化的方法
    xxx==null和xxx.equals(null)的区别
    Java+7入门经典
    《UNIX环境高级编程》笔记--read函数,write函数,lseek函数
  • 原文地址:https://www.cnblogs.com/zhoading/p/9678126.html
Copyright © 2011-2022 走看看