1. 程式人生 > >Nginx中的驚群現象解決方法

Nginx中的驚群現象解決方法

int str err 成功 web 超出 ror ket 什麽是

*什麽是驚群現象?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鎖的問題。。其超出了本篇的範圍。。。就不在這裏繼續討論了。。明天加油。。。→_→*

Nginx中的驚群現象解決方法