Mbsky

nginx惊群

This project is maintained by wangfakang

nginx惊群问题简单分析:

内容:

一:惊群含义

二:nginx如何解决惊群

三:何时释放该锁

四:相应代码解析

一.惊群含义:

昨天所说的惊群含义是指:

二.nginx是解决惊群

三.获得的锁何时释放

四.代码解析

    void
    ngx_process_events_and_timers(ngx_cycle_t *cycle)
    {
    ngx_uint_t  flags;
    ngx_msec_t  timer, delta;

    if (ngx_timer_resolution) {
        timer = NGX_TIMER_INFINITE;
        flags = 0;

    } else {
        timer = ngx_event_find_timer();
        flags = NGX_UPDATE_TIME;

    #if (NGX_THREADS)

        if (timer == NGX_TIMER_INFINITE || timer > 500) {
            timer = 500;
        }

    #endif
    }

    if (ngx_use_accept_mutex) {
        //表示当前进程的负载超过了最大连接数的7/8
        if (ngx_accept_disabled > 0) {
            ngx_accept_disabled--;

        } else {
            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
                return;
            }

            if (ngx_accept_mutex_held) {
                flags |= NGX_POST_EVENTS;

            } else {// 不让其平凡的获取到锁   
                if (timer == NGX_TIMER_INFINITE
                    || timer > ngx_accept_mutex_delay)
                {
                    timer = ngx_accept_mutex_delay;
                }
            }
        }
    }

    delta = ngx_current_msec;

    (void) ngx_process_events(cycle, timer, flags);

    delta = ngx_current_msec - delta;

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "timer delta: %M", delta);
    //处理新来的事件建立连接
    if (ngx_posted_accept_events) {
        ngx_event_process_posted(cycle, &ngx_posted_accept_events);
    }
    //处理完了就把其锁给释放了,让其新的连接可以被其尽快处理
    if (ngx_accept_mutex_held) {
        ngx_shmtx_unlock(&ngx_accept_mutex);
    }

    if (delta) {
        ngx_event_expire_timers();
    }

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                   "posted events %p", ngx_posted_events);
    //锁释放了才处理已经建立好的事件(已经完成了三次握手的事件)
    if (ngx_posted_events) {
        if (ngx_threaded) {
            ngx_wakeup_worker_thread(cycle);

        } else {
            ngx_event_process_posted(cycle, &ngx_posted_events);
        }
    }
    }

  ngx_int_t
    ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
    {
    //获取锁操作
    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,表示当前进程已经获取到锁    
        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) {
            ngx_shmtx_unlock(&ngx_accept_mutex);
            return NGX_ERROR;
        }

        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);
    //表示此次没有获取到锁,但是上次获取到锁,此时会把当前work的epoll中删除监听的端口事件
    if (ngx_accept_mutex_held) {
        if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
            return NGX_ERROR;
        }

        ngx_accept_mutex_held = 0;
    }

    return NGX_OK;
    }

有问题反馈

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

关于作者

Linux\nginx\golang\c\c++爱好者

欢迎一起交流 一起学习