nginx解析配置檔案,将解析出來得配置存放在ngx_cycle_s的conf_ctx中,conf_ctx是個四級指針,因為儲存這些配置需要context,而這些context是有層級關系,最終的配置結構如圖:
http子產品的配置有些複雜,由于server的配置還可以出現在http子產品中,同時location的配置可以出現在http子產品或者server子產品中,是以對于http來說也就是最上面的那個ngx_http_ctx_conf_t有srv_conf和loc_conf是十分有必要的,這兩個指針後面的結構體數組儲存了在http中的那些server的和location的配置。同樣對于每個server來說,不需要單獨的main配置了,直接引用main的就可以。每個server必須有自己單獨的ngx_http_core_srv_conf_t,來儲存目前server塊内的配置,這個配置最後會和http的裡面的ngx_http_core_srv_conf_t做merge,這個merge是把父server的配置merge到子server配置上面。對于location的配置,在http和server中都可以配置,那麼merge的操作需要首先把http的location配置merge到每個server配置中,然後每個server的location配置再和每個location子產品中的配置進行merge,這裡location配置需要merge兩次。舉例ngx_http_core_module子產品merge的過程:
merge過程是按照module一個一個module的merge,第一步從main配置裡面的servers,周遊每個server,把main裡面的server配置merge到每個server的配置中,然後把main裡面的location配置merge到每個server的location的配置中。第二步再次周遊每個server的locations,把這個server的location的配置merge到具體的每個location中。
代碼:
- static char *
- ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
- ngx_http_module_t *module, ngx_uint_t ctx_index) //cmcf代表http的main配置
- {
- char *rv;
- ngx_uint_t s;
- ngx_http_conf_ctx_t *ctx, saved;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_srv_conf_t **cscfp;
- cscfp = cmcf->servers.elts; //得到servers數組,cmcf是main層的配置
- ctx = (ngx_http_conf_ctx_t *) cf->ctx; //ctx是main的 ngx_http_conf_ctx_t
- saved = *ctx;
- rv = NGX_CONF_OK;
- for (s = 0; s < cmcf->servers.nelts; s++) { //周遊每個server,把main的配置merge到每個server中
- /* merge the server{}s' srv_conf's */
- ctx->srv_conf = cscfp[s]->ctx->srv_conf;
- if (module->merge_srv_conf) { //調用子產品的merge server操作
- //save.srv_conf是父server配置,cscf->ctx->srv_conf是目前server的配置,相當于圖中的第一步
- rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
- cscfp[s]->ctx->srv_conf[ctx_index]);
- if (rv != NGX_CONF_OK) {
- goto failed;
- }
- }
- //調用子產品的merge location操作,把父location配置merge到每個server的location配置相當于圖中的第一步
- if (module->merge_loc_conf) {
- /* merge the server{}'s loc_conf */
- ctx->loc_conf = cscfp[s]->ctx->loc_conf;
- rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
- cscfp[s]->ctx->loc_conf[ctx_index]);
- if (rv != NGX_CONF_OK) {
- goto failed;
- }
- /* merge the locations{}' loc_conf's */
- clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
- //該merge每個server的location配置到每個location的配置中了,相當于圖中的第二步
- rv = ngx_http_merge_locations(cf, clcf->locations,
- cscfp[s]->ctx->loc_conf,
- module, ctx_index);
- if (rv != NGX_CONF_OK) {
- goto failed;
- }
- }
- }
server中location和location的merge過程
- static char *
- ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
- void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
- {
- char *rv;
- ngx_queue_t *q;
- ngx_http_conf_ctx_t *ctx, saved;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_location_queue_t *lq;
- if (locations == NULL) {
- return NGX_CONF_OK;
- }
- ctx = (ngx_http_conf_ctx_t *) cf->ctx;
- saved = *ctx;
- for (q = ngx_queue_head(locations); //周遊server中的locations隊列
- q != ngx_queue_sentinel(locations);
- q = ngx_queue_next(q))
- {
- lq = (ngx_http_location_queue_t *) q;
- clcf = lq->exact ? lq->exact : lq->inclusive;
- ctx->loc_conf = clcf->loc_conf;
//loc_conf代表server下location配置,clcf->loc_conf代表每個location的配置
- rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
- clcf->loc_conf[ctx_index]);
- if (rv != NGX_CONF_OK) {
- return rv;
- }
- rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
- module, ctx_index); //遞歸嵌套location
- if (rv != NGX_CONF_OK) {
- return rv;
- }
- }