天天看點

Nginx 配置初始化過程

nginx解析配置檔案,将解析出來得配置存放在ngx_cycle_s的conf_ctx中,conf_ctx是個四級指針,因為儲存這些配置需要context,而這些context是有層級關系,最終的配置結構如圖:

Nginx 配置初始化過程

    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的過程:

Nginx 配置初始化過程

    merge過程是按照module一個一個module的merge,第一步從main配置裡面的servers,周遊每個server,把main裡面的server配置merge到每個server的配置中,然後把main裡面的location配置merge到每個server的location的配置中。第二步再次周遊每個server的locations,把這個server的location的配置merge到具體的每個location中。

代碼:

  1. static char *
  2. ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
  3.     ngx_http_module_t *module, ngx_uint_t ctx_index) //cmcf代表http的main配置
  4.     char *rv; 
  5.     ngx_uint_t s; 
  6.     ngx_http_conf_ctx_t *ctx, saved;
  7.     ngx_http_core_loc_conf_t *clcf;
  8.     ngx_http_core_srv_conf_t **cscfp;
  9.     cscfp = cmcf->servers.elts;             //得到servers數組,cmcf是main層的配置
  10.     ctx = (ngx_http_conf_ctx_t *) cf->ctx; //ctx是main的 ngx_http_conf_ctx_t
  11.     saved = *ctx;
  12.     rv = NGX_CONF_OK;
  13.     for (s = 0; s < cmcf->servers.nelts; s++) { //周遊每個server,把main的配置merge到每個server中
  14.         /* merge the server{}s' srv_conf's */
  15.         ctx->srv_conf = cscfp[s]->ctx->srv_conf; 
  16.         if (module->merge_srv_conf) {           //調用子產品的merge server操作
  17.     //save.srv_conf是父server配置,cscf->ctx->srv_conf是目前server的配置,相當于圖中的第一步
  18.             rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
  19.                                         cscfp[s]->ctx->srv_conf[ctx_index]); 
  20.             if (rv != NGX_CONF_OK) {
  21.                 goto failed;
  22.             } 
  23.         } 
  24.   //調用子產品的merge location操作,把父location配置merge到每個server的location配置相當于圖中的第一步
  25.         if (module->merge_loc_conf) {
  26.             /* merge the server{}'s loc_conf */
  27.             ctx->loc_conf = cscfp[s]->ctx->loc_conf;
  28.             rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
  29.                                         cscfp[s]->ctx->loc_conf[ctx_index]);
  30.             if (rv != NGX_CONF_OK) {
  31.                 goto failed;
  32.             } 
  33.             /* merge the locations{}' loc_conf's */
  34.             clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
  35. //該merge每個server的location配置到每個location的配置中了,相當于圖中的第二步
  36.             rv = ngx_http_merge_locations(cf, clcf->locations,
  37.                                           cscfp[s]->ctx->loc_conf,
  38.                                           module, ctx_index); 
  39.             if (rv != NGX_CONF_OK) {
  40.                 goto failed;
  41.             }
  42.         }
  43.     }

    server中location和location的merge過程

  1. static char *
  2. ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
  3.     void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
  4. {
  5.     char *rv;
  6.     ngx_queue_t *q;
  7.     ngx_http_conf_ctx_t *ctx, saved;
  8.     ngx_http_core_loc_conf_t *clcf;
  9.     ngx_http_location_queue_t *lq;
  10.     if (locations == NULL) {
  11.         return NGX_CONF_OK;
  12.     }
  13.     ctx = (ngx_http_conf_ctx_t *) cf->ctx;
  14.     saved = *ctx;
  15.     for (q = ngx_queue_head(locations);      //周遊server中的locations隊列
  16.          q != ngx_queue_sentinel(locations);
  17.          q = ngx_queue_next(q))
  18.     {
  19.         lq = (ngx_http_location_queue_t *) q;
  20.         clcf = lq->exact ? lq->exact : lq->inclusive; 
  21.         ctx->loc_conf = clcf->loc_conf;

//loc_conf代表server下location配置,clcf->loc_conf代表每個location的配置

  1.         rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
  2.                                     clcf->loc_conf[ctx_index]); 
  3.         if (rv != NGX_CONF_OK) {
  4.             return rv;
  5.         }
  6.         rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
  7.                                       module, ctx_index);        //遞歸嵌套location
  8.         if (rv != NGX_CONF_OK) {
  9.             return rv;
  10.         }
  11.     }

繼續閱讀