1. 程式人生 > >Nginx 事件機制介紹

Nginx 事件機制介紹

先看幾個主要方法

  • ngx_add_channel_event 主要是把事件註冊到事件池中,並且新增事件 handler,具體要結合後面的事件機制來展開。

  • ngx_write_channel 主要是將資料寫入到 pipe 中:

       n = sendmsg(s, &msg, 0);

       Top of Form

       Bottom of Form

  • ngx_read_channel 從 pipe 中讀取資料:n = recvmsg(s, &msg, 0);

接下來分析事件模組工作流程

ngx_event模組結構

ngx_events_module 的資料結構如下:

ngx_module_t ngx_events_module = { 

        NGX_MODULE_V1, 

        &ngx_events_module_ctx, /* module context */

        ngx_events_commands, /* module directives */

        NGX_CORE_MODULE, /* module type */ 

        NULL, /* init master */ 

        NULL, /* init module */ 

        NULL, /* init process */ 

        NULL, /* init thread */ 

        NULL, /* exit thread */ 

        NULL, /* exit process */ 

        NULL, /* exit master */

        NGX_MODULE_V1_PADDING 

};

ngx_event 模組初始化

static ngx_command_t ngx_events_commands[] = {   

        {

                ngx_string("events") , 

                NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS , 

                 ngx_events_block, 0, 0, NULL 

         },   

        ngx_null_command

};

通過 ngx_events_commands 陣列可以知道,event 模組初始化函式為 ngx_events_block,該函式工作內容如下:

  1. 建立模組 context 結構

  2. 呼叫所有 NGX_EVENT_MODULE 模組的 create_conf

  3. 解析 event 配置

  4. 呼叫所有 NGX_EVENT_MODULE 模組的 init_conf

ngx_core_event模組初始化

ngx_core_event_module 是在 ngx_cycle_init 的時候初始化的:

for (i = 0; ngx_modules[i]; i++) { 

        if (ngx_modules[i]->init_module) { 

                if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ 

                        exit(1); 

                } 

         } 

}

我們先來看下 ngx_core_event_module 的結構:

ngx_module_t ngx_event_core_module = { 

        NGX_MODULE_V1, 

        &ngx_event_core_module_ctx, /* module context */

        ngx_event_core_commands, /* module directives */

        NGX_EVENT_MODULE, /* module type */ 

        NULL, /* init master */

        ngx_event_module_init, /* init module */

        ngx_event_process_init, /* init process */ 

        NULL, /* init thread */ 

        NULL, /* exit thread */ 

        NULL, /* exit process */ 

        NULL, /* exit master */ NGX_MODULE_V1_PADDING

};

ngx_event_module_init 實現了初始化過程,該過程分以下幾個步驟:

  1. 連線數校驗

  2. 初始化互斥鎖

事件程序初始化

在工作執行緒初始化的時候,將會呼叫 ngx_event_process_init:

for (i = 0; ngx_modules[i]; i++) { 

        if (ngx_modules[i]->init_process)  { 

                if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { /*fatal */ 

                      exit(2); 

                } 

        } 

}

ngx_event_process_init 該過程分以下幾步:

  1. 設定 ngx_accept_mutex_held

  2. 初始化定時器

  3. 初始化真正的事件引擎(linux 中為 epoll)

  4. 初始化連線池

  5. 新增 accept 事件

ngx_process_events_and_timers 事件處理開始工作

工作流程如下:

  1. ngx_trylock_accept_mutex 當獲取到標誌位後才進行 accept 事件註冊。

  2. ngx_process_events 處理事件

  3. 釋放 accept_mutex 鎖

  4. 處理定時器事件

  5. ngx_event_process_posted 處理 posted 佇列的事件

ngx 定時器實現

ngx 的定時器利用了紅黑樹的實現

ngx 驚群處理

accept_mutex 解決了驚群問題,雖然linux的新核心已經解決了這個問題,但是ngx 是為了相容。

整體原理圖: