標籤:style class blog code http ext
當Nginx檢測到設定檔中存在配置塊http{}時,會建立一個ngx_http_conf_ctx_t結構體,該結構體定義如下:
typedef struct { void **main_conf; // 每個指標元素指向所有由HTTP模組的create_main_conf方法產生的結構體 void **srv_conf; // 每個指標元素指向所有由HTTP模組的create_srv_conf方法產生的結構體 void **loc_conf; // 每個指標元素指向所有由HTTP模組的create_loc_conf方法產生的結構體} ngx_http_conf_ctx_t;
具體來說,架構代碼在遇到http{}時會調用核心模組ngx_http_module(HTTP架構的一部分)中解析配置項的ngx_http_block方法,該方法的關於產生和配置ngx_http_conf_ctx_t結構體的過程大致如下,代碼位於ngx_http.c中:
ngx_http_conf_ctx_t *ctx; // 定義一個該結構體的指標 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); // 分配該結構體空間ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); // 分配數組存放指標ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); // 分配數組存放指標ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); // 分配數組存放指標 for (m = 0; ngx_modules[m]; m++){ if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; if (module->create_main_conf) { /* 依次調用所有HTTP模組的create_main_conf方法 * 產生的結構體指標放入上面分配了空間的main_conf指標數組中 */ ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { /* 依次調用所有HTTP模組的create_srv_conf方法 * 產生的結構體指標放入上面分配了空間的srv_conf指標數組中 */ ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_loc_conf) { /* 依次調用所有HTTP模組的create_loc_conf方法 * 產生的結構體指標放入上面分配了空間的loc_conf指標數組中 */ ctx->loc_conf[mi] = module->create_loc_conf(cf); if (ctx->loc_conf[mi] == NULL) { return NGX_CONF_ERROR; } }}
server{}和location{}和http{}相似:
- 當遇到server{}配置塊時,建立ngx_http_conf_ctx_t結構體,main_conf成員指向父配置塊所對應的ngx_http_conf_ctx_t結構體,srv_conf成員和loc_conf成員儲存HTTP模組通過create_srv_conf和create_loc_conf方法產生的配置結構體指標。
- 當遇到location{}配置塊時,建立ngx_http_conf_ctx_t結構體,main_conf成員指向父配置塊對應ngx_http_conf_ctx_t結構體,srv_conf成員指向父配置塊ngx_http_conf_ctx_t結構體的srv_conf元素,loc_conf儲存HTTP模組create_loc_conf方法產生的配置結構體指標。
三個ngx_http_conf_ctx_t結構體分別對應http{}、server{}、location{},它們之間的關係用可以清晰的說明:
下面介紹解析HTTP配置的大致流程:
- Nginx進程主迴圈調用設定檔解析器解析nginx.conf設定檔。
- 設定檔解析器發現http{},啟動HTTP架構,也就是核心模組ngx_http_module。
- 核心模組調用ngx_command_t中的set回呼函數,也就是ngx_http_block方法。
- 初始化所有HTTP模組的序號,分配一個ngx_http_conf_ctx_t結構體並初始化三個數組。
- 調用每個HTTP模組的create_main_conf、create_srv_conf、create_loc_conf方法分配儲存配置項參數的結構體,返回的指標儲存在ngx_http_conf_ctx_t結構體中。
- 調用每個HTTP模組的preconfiguration方法。
- 設定檔解析器檢測到一個配置項後,遍曆所有HTTP模組的ngx_command_t數組,看有沒有能夠和配置項名稱匹配的ngx_command_t結構體,有則調用ngx_command_t結構中的set方法來處理配置項。
- 設定檔解析器繼續檢測配置項,遇到server{}或location{}則以類似的方法遞迴解析塊中的配置項,不過此時負責解析配置項的模組變成了ngx_http_core_module,方法在上面已經詳細說明了。
- 設定檔解析器解析到http{}尾端,返回HTTP架構ngx_http_module。
- 調用merge_srv_conf和merge_loc_conf等方法合并配置項結構體。
- HTTP架構處理完http配置項,ngx_command_t的set回調方法返回。
- 設定檔解析器返回Nginx主迴圈,Nginx進程啟動Web伺服器。
參考:《深入理解Nginx》 P140-P143.