您好,登錄后才能下訂單哦!
這篇文章主要介紹“nginx事件模塊結構體的詳解”,在日常操作中,相信很多人在nginx事件模塊結構體的詳解問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”nginx事件模塊結構體的詳解”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
nginx的事件核心模塊主要有兩個:ngx_events_module
和ngx_event_core_module
。這兩個模塊的主要區別在于,ngx_events_module的類型為NGX_CORE_MODULE
,其本質上雖然是核心模塊類型,但是卻是事件模塊的一個驅動點,其解析的配置項為events {},并且會創建用于存儲事件模塊相關配置的結構體;
而ngx_event_core_module的類型則是NGX_EVENT_MODULE
,這個模塊的配置對象中會存儲事件模塊的基礎配置對象,其主要作用是解析events{}配置塊中的子配置項。
下面我們就來看一下這兩個模塊的基礎配置。
1. ngx_events_module
如下是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 }; static ngx_core_module_t ngx_events_module_ctx = { ngx_string("events"), NULL, ngx_event_init_conf }; 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_module
模塊的定義中,其module context指向的是ngx_events_module_ctx
,也即第二個結構體的配置,而module directives指向的則是ngx_events_commands
,也即第三個結構體的定義。可以看到,ngx_events_commands
中只定義了一個events配置項,而這個配置項的類型為NGX_CONF_BLOCK,也就是說其是一個配置塊的類型,這里我們就理解了,這個command對應的就是我們在nginx.conf中使用的events {}配置塊,而這個配置塊的解析則是通過ngx_events_block()
方法進行的。
我們知道,在nginx的核心配置對象ngx_cycle_t中的conf_ctx數組中,每個模塊在數組對應的位置都會有一個配置對象,同理,這里的核心模塊也會有一個配置對象,但是上面的第二個結構體ngx_events_module_ctx
中的第二個屬性值為NULL,也就是說這里的事件模塊的定義中是沒有創建配置對象的方法的,但是卻有初始化配置對象的方法,也即第三個屬性值ngx_event_init_conf()
方法。
那么這里事件模塊的配置對象是在哪里創建的呢?
其實其就是在解析配置對象的時候進行的,也即在執行解析events {}
配置塊的ngx_events_block()
方法中進行的。該方法本質上只是創建了一個指針數組,然后將其賦值給nginx核心和值對象的ngx_cycle_t的conf_ctx的對應位置。
2. ngx_event_core_module
在介紹ngx_event_core_module
模塊之前,我們首先需要講解一下事件模塊的接口定義:
typedef struct { // 事件模塊的名稱 ngx_str_t *name; // 在解析配置項前,這個回調方法用于創建存儲配置項參數的結構體 void *(*create_conf)(ngx_cycle_t *cycle); // 在解析配置項完成后,init_conf()方法會被調用,用以綜合處理當前事件模塊感興趣的全部配置項 char *(*init_conf)(ngx_cycle_t *cycle, void *conf); // 對于事件驅動機制,每個事件模塊需要實現的10個抽象方法 ngx_event_actions_t actions; } ngx_event_module_t; typedef struct { // 添加事件方法,它負責把一個感興趣的事件添加到操作系統提供的事件驅動機制(epoll、kqueue等)中, // 這樣,在事件發生后,將可以在調用下面的process_events時獲取這個事件 ngx_int_t (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); // 刪除事件方法,它把一個已經存在于事件驅動機制中的事件移除,這樣以后即使這個事件發生, // 調用process_events()方法時也無法再獲取這個事件 ngx_int_t (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); // 啟用一個事件,目前事件框架不會調用這個方法,大部分事件驅動模塊對于該方法的實現都是 // 與上面的add()方法完全一致的 ngx_int_t (*enable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); // 禁用一個事件,目前事件框架不會調用這個方法,大部分事件驅動模塊對于該方法的實現都是 // 與上面的del()方法完全一致的 ngx_int_t (*disable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); // 向事件驅動機制中添加一個新的連接,這意味著連接上的讀寫事件都添加到事件驅動機制中了 ngx_int_t (*add_conn)(ngx_connection_t *c); // 從事件驅動機制中移除一個連接的讀寫事件 ngx_int_t (*del_conn)(ngx_connection_t *c, ngx_uint_t flags); ngx_int_t (*notify)(ngx_event_handler_pt handler); // 在正常的工作循環中,將通過調用process_events()方法來處理事件。 // 這個方法僅在ngx_process_events_and_timers()方法中調用,它是處理、分發事件的核心 ngx_int_t (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags); // 初始化事件驅動模塊的方法 ngx_int_t (*init)(ngx_cycle_t *cycle, ngx_msec_t timer); // 退出事件驅動模塊前調用的方法 void (*done)(ngx_cycle_t *cycle); } ngx_event_actions_t;
nginx的事件模塊主要有兩個配置結構體:ngx_event_module_t
和ngx_event_actions_t
兩個。從上面的定義中可以看出,ngx_event_module_t
結構體是引用了ngx_event_actions_t
的。
ngx_event_module_t
的作用主要是創建和初始化當前模塊所需要的配置結構體,而ngx_event_actions_t則主要定義了當前事件模塊處理各個事件的方式,這個接口典型的實現接口是nginx定義的各個事件模型,比如epoll的ngx_epoll_module_ctx.actions
和kqueue的ngx_kqueue_module_ctx.actions
。從這里就可以看出,事件模塊的定義抽象了各個處理事件的模型的相關處理方法。
對于事件模塊而言,其有一個模塊是用于存儲事件相關的基礎配置的,即ngx_event_core_module
,雖然實現了ngx_event_module_t
接口,但是其不進行具體的事件處理。如下是ngx_event_core_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 */ // 該方法主要是在master進程啟動的過程中調用的,用于初始化時間模塊 ngx_event_module_init, /* init module */ // 該方法是在各個worker進程啟動之后調用的 ngx_event_process_init, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; static ngx_event_module_t ngx_event_core_module_ctx = { &event_core_name, ngx_event_core_create_conf, /* create configuration */ ngx_event_core_init_conf, /* init configuration */ // ngx_event_core_module_ctx并不直接負責TCP網絡事件的驅動, // 因而這里的ngx_event_actions_t中的方法都為NULL {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} }; static ngx_command_t ngx_event_core_commands[] = { // 連接池的大小,也即每個worker進程中支持的TCP最大連接數,它與connections配置項的意義是重復的 {ngx_string("worker_connections"), NGX_EVENT_CONF | NGX_CONF_TAKE1, ngx_event_connections, 0, 0, NULL}, // 確定選擇哪一個事件模塊作為事件驅動機制 {ngx_string("use"), NGX_EVENT_CONF | NGX_CONF_TAKE1, ngx_event_use, 0, 0, NULL}, // 對應于ngx_event_s中的available屬性,對于epoll事件驅動模式來說,意味著在接收到一個新連接事件時, // 調用accept以盡可能多地接收連接 {ngx_string("multi_accept"), NGX_EVENT_CONF | NGX_CONF_FLAG, ngx_conf_set_flag_slot, 0, offsetof(ngx_event_conf_t, multi_accept), NULL}, // 確定是否使用accept_mutex負載均衡鎖,默認為開啟 {ngx_string("accept_mutex"), NGX_EVENT_CONF | NGX_CONF_FLAG, ngx_conf_set_flag_slot, 0, offsetof(ngx_event_conf_t, accept_mutex), NULL}, // 啟用accept_mutex負載均衡鎖后,延遲accept_mutex_delay毫秒后再試圖處理新連接事件 {ngx_string("accept_mutex_delay"), NGX_EVENT_CONF | NGX_CONF_TAKE1, ngx_conf_set_msec_slot, 0, offsetof(ngx_event_conf_t, accept_mutex_delay), NULL}, // 需要對來自指定IP的TCP連接打印debug級別的調試日志 {ngx_string("debug_connection"), NGX_EVENT_CONF | NGX_CONF_TAKE1, ngx_event_debug_connection, 0, 0, NULL}, ngx_null_command };
在事件模塊的定義中,module context指向的是一個ngx_event_module_t
結構體,這里的ngx_event_core_module
的module context指向的就是第二個結構體定義的ngx_event_core_module_ctx
,而ngx_event_core_module_ctx
中則定義了當前核心模塊創建配置對象和初始化配置對象的方法,可以看到,其actions屬性中的值全部為NULL,這是因為該模塊并不負責處理具體的事件處理方案,而是負責核心結構體的創建和初始化,nginx也會保證這個模塊在所有的事件模塊中最先被調用,其余各個事件模塊也可以引用該模塊所存儲的基礎配置數據。
在ngx_event_core_module
中第三個屬性ngx_event_core_commands
指向的是上面的第三個結構體,這個結構體中定義了當前事件模塊所能使用的各個配置項的基本配置以及解析這些配置項的方法。
這里我們需要著重強調ngx_event_core_module
中的第六個和第七個屬性,這兩個屬性指向的是都是某個方法,第六個屬性init module的主要是在nginx啟動過程中解析完nginx.conf
配置文件之后執行,其作用是對當前模塊進行初始化的工作,而第七個屬性init process主要是在nginx啟動worker進程之后worker進程開始執行主循環之前調用的,其作用是進行worker進程執行前的初始化工作。
3. 模塊方法的執行流程
通過上面的介紹我們大致了解了定義事件模塊的兩個核心模塊的主要方法及其作用,這里則主要是對這些方法的執行流程進行講解,如下是其流程示意圖:
對于上面的,這里需要對其各個步驟的功能進行說明:
1.解析nginx.conf
文件,當遇到events
配置項時,就使用ngx_evetns_block()
方法對其進行解析;
2.創建用于存儲各個事件模塊存儲配置項的結構體的數組;
3.采用遞歸的方式解析events
配置塊中的子配置項;
4.依次檢查事件核心模塊的配置項,如果其沒有賦值,則對其賦一個默認值;
5.檢查是否創建了存儲事件模塊配置項的數組,該檢查的主要目的是判斷核心模塊是否成功初始化了;
6.主要是通過解析得到的配置項,設置諸如時間定時器的執行頻率、可打開的文件句柄限制和初始化記錄統計數據的屬性;
7.在worker
進程中調用,用于初始化worker
進程運行所需要的環境,比如初始化事件隊列、初始化事件模型、添加時間更新的定時任務等;
到此,關于“nginx事件模塊結構體的詳解”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。