[nginx源碼分析]配置合併

整個ngx_http_block中的ngx_conf_parse配置解析完成,,後面主要對配置文件進行優化。

優化可以分爲以下:

1 配置作用域合併

2location劃分

3 http header回調初始化hash

4 初始化http收包回調函數

5 server中的server_name形成hash


本篇主要說配置合併的事情

配置作用域合併

主要是http、server、location,http作用域最大、server其次、location最精細化。合併的主要流程是,同一個模塊中的上下文變量可以存在在不同的作用域,可以在配置文件中的http作用域,也可以在server作用域,還可以寫在location作用域,如果該變量在server作用域沒有設置,但是http作用域配置文件中設置了該值,那麼server作用域的該值,就會被http作用域的合併掉,使用http作用的值,同理location和server合併。那麼下面來看核心代碼。

cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];                          //獲取http中的main_conf[ngx_http_core_module.ctx_index] 中的信息,包括server信息
      cscfp = cmcf->servers.elts;
  
      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;
  
          /* init http{} main_conf's */
  
          if (module->init_main_conf) {                                               //調用每個http module的init_main_conf函數,來初始化那些用戶沒設置的值
              rv = module->init_main_conf(cf, ctx->main_conf[mi]);
              if (rv != NGX_CONF_OK) {
                  goto failed;
              }
          }
  
          rv = ngx_http_merge_servers(cf, cmcf, module, mi);                                                                                                                                                                             
          if (rv != NGX_CONF_OK) {
              goto failed;
          }
      }

主要是獲取server上下文cscfp,遍歷NGX_HTTP_MODULE調用模塊的init_main_conf函數,進行初始化和ngx_http_merge_servers進行作用域合併。我們就列舉最核心的模塊ngx_http_core_module的init_main_conf和ngx_http_merge_servers,分析完ngx_http_core_module的這兩個函數,你就會清楚作用域合併原理。

ngx_http_core_module的init_main_conf回調函數爲ngx_http_core_init_main_conf函數,

static char *
 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)                                                                                                                                                                               
 {
     ngx_http_core_main_conf_t *cmcf = conf;
 	 //如果未設置,給一個默認值
     if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
         cmcf->server_names_hash_max_size = 512;
     }
 	 //如果未設置,給一個默認值
     if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
         cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
     }
 	 //.如果未設置,那麼給一個默認值
     cmcf->server_names_hash_bucket_size =
             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
     if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
         cmcf->variables_hash_max_size = 512;
     }
 
     if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
         cmcf->variables_hash_bucket_size = 64;
     }
 
     cmcf->variables_hash_bucket_size =
                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
 
     if (cmcf->ncaptures) {
         cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
     }
 
     return NGX_CONF_OK;
 }

從上面函數可以看到,如果用戶沒有在配置文件設置該模塊main作用域(即http作用域)相應的值,那麼就給他們賦值一個默認值。

作用域合併函數:

cf是http上下文

cmcf是ngx_http_core_module在main的上下文(即http上下文)

module是遍歷的模塊(ngx_modules)

mi 是該模塊在http上下文的索引,對應的是ngx_module[m]

ngx_http_merge_servers(cf,cmcf, module, mi)

核心代碼:

 for (s = 0; s < cmcf->servers.nelts; s++) {
  
          /* merge the server{}s' srv_conf's */
  
          ctx->srv_conf = cscfp[s]->ctx->srv_conf;
  
          if (module->merge_srv_conf) {
              rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index], /*http的srv_conf*/
             cscfp[s]->ctx->srv_conf[ctx_index]);//server的srv_conf進行合併
              if (rv != NGX_CONF_OK) {
                  goto failed;
              }
          }
  
          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];
  
              rv = ngx_http_merge_locations(cf, clcf->locations,
                                            cscfp[s]->ctx->loc_conf,
                                            module, ctx_index);
              if (rv != NGX_CONF_OK) {
                  goto failed;
              }
          }                                                                                                                                                                                                                              
      }

ngx_http_merge_servers調用者(外層函數)是對模塊(ngx_modules)進行遍歷,也就是說對每一個模塊的每一個server都會進行處理。然後我們聚焦於ngx_http_merge_servers函數,主要是對於一個模塊合併該模塊的http、server、location不同上下文的變量,http->server->location會越來越精準化,就像是c++的作用域一樣,http可以看作是http作用域,server可以看作是server作用域,location相當於塊作用域,內層作用域可以隱藏到外層作用域和這裏的合併是一個道理。

ngx_http_merge_servers核心的兩個函數是merge_srv_conf和merge_loc_conf,merge_srv_conf主要合併http和server server上下文,merge_loc_conf主要合併http和server的loc上下文, ngx_http_merge_locations主要合併server和loc的loc上下文,同時該函數還進行location的遞歸調用,用於合併location中的location。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章