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,該函式工作內容如下:
-
建立模組 context 結構
-
呼叫所有 NGX_EVENT_MODULE 模組的 create_conf
-
解析 event 配置
-
呼叫所有 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 實現了初始化過程,該過程分以下幾個步驟:
-
連線數校驗
-
初始化互斥鎖
事件程序初始化
在工作執行緒初始化的時候,將會呼叫 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 該過程分以下幾步:
-
設定 ngx_accept_mutex_held
-
初始化定時器
-
初始化真正的事件引擎(linux 中為 epoll)
-
初始化連線池
-
新增 accept 事件
ngx_process_events_and_timers 事件處理開始工作
工作流程如下:
-
ngx_trylock_accept_mutex 當獲取到標誌位後才進行 accept 事件註冊。
-
ngx_process_events 處理事件
-
釋放 accept_mutex 鎖
-
處理定時器事件
-
ngx_event_process_posted 處理 posted 佇列的事件
ngx 定時器實現
ngx 的定時器利用了紅黑樹的實現
ngx 驚群處理
accept_mutex 解決了驚群問題,雖然linux的新核心已經解決了這個問題,但是ngx 是為了相容。
整體原理圖: