標籤:div master and 問題 pre block strong 命名 儲存位置
HTTP架構是Nginx基礎架構的一部分,Nginx的其它底層架構如master-worker進程模型、event模組、mail 模組等。
HTTP架構代碼主要有2個模組組成:ngx_http_module和ngx_http_core_module;
我們編寫的HTTP模組需要註冊到HTTP架構上,才能融入HTTP請求的處理流程中。
當在nginx.conf中存在一個http{...}的配置時,即啟用了HTTP架構代碼,在nginx配置解析時,就已經為架構建立好了各種資料結構(尤其是HTTP模組的掛載);
當nginx收到請求時,請求完全按照HTTP架構建立好的這種邏輯進行處理。
一、HTTP模組開發基礎
開發一個HTTP模組,需要下面幾個資料結構:
1. HTTP模組配置結構
用於儲存從設定檔讀進來的相關指令參數;配置模組的context有三種,分別是main、server和location,它們分別位于于http{...}、server{...}和location{...}上下文中。其名稱約定如下:
ngx_http_<module name>_(main|srv|loc)_conf_t
2.HTTP 模組配置指令模組的指令是定義在一個叫做
ngx_command_t的靜態數組中的;ngx_command_t數組以ngx_null_command為終結符。 struct ngx_command_t {
ngx_str_t name; // 指令名稱
ngx_uint_t type; // 指令所在的context和包含的參數個數
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // 解析配置,並將參數存入模組配置結構體中
ngx_uint_t conf; // 指令參數的儲存位置
ngx_uint_t offset; // 指令參數的儲存位移量
void *post;
};其中,
type 成員表明這個指令允許出現的context、參數個數: * NGX_HTTP_MAIN_CONF: 指令出現在main配置部分是合法的 * NGX_HTTP_SRV_CONF: 指令在server配置部分出現是合法的 config * NGX_HTTP_LOC_CONF: 指令在location配置部分出現是合法的 * NGX_HTTP_UPS_CONF: 指令在upstream配置部分出現是合法的 * NGX_CONF_NOARGS: 指令沒有參數 * NGX_CONF_TAKE1: 指令讀入1個參數 * NGX_CONF_TAKE7: 指令讀入7個參數 * NGX_CONF_FLAG: 指令讀入1個布爾型資料 ("on" or "off") * NGX_CONF_1MORE: 指令至少讀入1個參數 * NGX_CONF_2MORE: 指令至少讀入2個參數
set 成員是一個函數指標,用於模組參數解析,可以將設定檔中的模組參數傳遞給模組;該函數會在遇到指令時執行,函數有三個入參: a. 指向結構體 ngx_conf_t 的指標, 這個結構體裡包含需要傳遞給指令的參數
b. 指向結構體 ngx_command_t 的指標
c. 指向模組自訂配置結構體的指標 Nginx內部提供了多個函數用來儲存特定類型的資料,這些函數包括: * ngx_conf_set_flag_slot: 將 "on" or "off" 轉換成 1 or 0 * ngx_conf_set_str_slot: 將字串儲存為 ngx_str_t * ngx_conf_set_num_slot: 解析一個數字並儲存為int * ngx_conf_set_size_slot: 解析一個資料大小(如:"8k", "1m") 並儲存為size_t
conf 成員告訴Nginx把資料存在模組的哪個context中 * NGX_HTTP_MAIN_CONF_OFFSET * NGX_HTTP_SRV_CONF_OFFSET * NGX_HTTP_LOC_CONF_OFFSET
offset 成員確定儲存在結構體的哪個位置;
post 成員指向模組在讀配置的時候需要的一些零碎變數,一般為NULL。
3. HTTP模組上下文結構
靜態
ngx_http_module_t結構體,用來建立和合并三段context (main,server,location),其命名方式一般是:ngx_http_<module name>_module_ctx,typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf); // 在讀入配置前調用
ngx_int_t (*
postconfiguration)(ngx_conf_t *cf); // 在讀入配置後調用,用於掛載handler
void *(*create_main_conf)(ngx_conf_t *cf); // 在建立main配置時調用(比如,用來分配空間和設定預設值)
char *(*init_main_conf)(ngx_conf_t *cf, void *conf); // 在初始化main配置時調用(比如,把原來的預設值用nginx.conf讀到的值來覆蓋)
void *(*create_srv_conf)(ngx_conf_t *cf); // 在建立server配置時調用
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf); // 合并server和main配置時調用
void *(*
create_loc_conf)(ngx_conf_t *cf); // 建立location配置時調用,用於為指令參數結構體分配記憶體和初始化
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf); // 合并location和server配置時調用
} ngx_http_module_t;
這些回調是在ngx_http_block()解析http{...}配置時完成的:
當遇到一個 http{...} 時,HTTP架構會調用所有HTTP模組可能實現的create_main_conf、create_srv_conf、create_loc_conf產生儲存main層級配置參數結構體;
當遇到一個server{...}時,HTTP架構會調用所有HTTP模組可能實現的create_srv_conf、create_loc_conf產生儲存server層級配置參數結構體;
當遇到一個location{...}時,HTTP架構會調用所有HTTP模組可能實現的create_loc_conf產生儲存location層級配置參數結構體;
因此,我們開發的HTTP模組中create_loc_conf方法被調用的次數等於http{...}、server{...}、location{...}在nginx.conf出現的次數之和;
create_srv_conf方法被調用的次數等於server{...}、location{...}在nginx.conf出現的次數之和;
由於只有一個http{...},所以create_main_conf方法只會被調用一次;
HTTP建立了如此多的結構體來存放配置項,是為瞭解決同名配置項的合并問題。
4、HTTP模組定義一個Nginx模組被定義為一個
ngx_module_t 結構,該結構體變數命名方式為ngx_http_<module-name>_module它包含模組的內容和指令執行方式,同時還包含一些回呼函數來處理線程/進程的建立和銷毀;模組定義在有的時候會被用作尋找的關鍵字,來尋找與特定模組相關聯的資料。
struct ngx_module_s {
ngx_uint_t ctx_index; // 在所有的HTTP模組中的序號
ngx_uint_t index; // 在所有模組中的序號
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;
ngx_uint_t version;
void *ctx; // 模組上下文
ngx_command_t *commands; // 模組配置指令
ngx_uint_t type; // 模組類型,HTTP模組應為NGX_HTTP_MODULE
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
注意:在configure之後產生的檔案 objs/ngx_modules.c 中包含了模組的編譯順序。
1、解析HTTP配置的流程
首先要理解 ngx_conf_parse() 的遞迴解析流程;
nginx在解析nginx.conf的時候,沒讀取一行配置項,就執行該配置項的解析回調(handler);
Nginx Http架構的理解