关于nginx配置解析中merge操作的探讨

我们先来看看http module的类型的结构体:
typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);

void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);

void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;

中间有两项被加粗的成员,这就是要讨论的重点了,其他的项都好说,这里有点不太明确的就是preconfiguration
和postconfiguration,这两个handler的一般作用分别是:
preconfiguration:设置一些全局预定义的变量,在之后的解析中可能要用到
postconfiguration: 字如其名,一般是在配置解析完之后,设置一些处理handler或者filter handler

关于merge,中文翻译一般为:合并,那么谁跟谁合并,为什么要合并,就是我们要讨论的问题!
这里先交代一个背景,关于nginx的配置信息组织结构。
http
|__server
| |__location
| |__location
|
|__server
|__location

nginx每当解析一个server或者location是都以一个ctx(类型是ngx_http_conf_ctx_t),即所谓的上下文变量来保存
当前(即局部)的配置,同时上层的ctx可以从cf->ctx的形式得到,在这个当前ctx中它的main_conf会继承上层,这点上
server和location是一样的处理,而若当前是server,那么它ctx中的src_conf和loc_conf需要重新创建,而location处理时,
则只会创建loc_conf,src_conf共享上层server的。

函数ngx_http_merge_servers:
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)
{
    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;

    // http block中配置的server块,都放在cmcf->servers这个数组中
    cscfp = cmcf->servers.elts;

    // 在外层的处理中cf->ctx的main_conf,srv_conf和loc_conf都已初始化过了
    // 但是大部分都是空壳,即简单的create,没有有针对配置的具体指令来设置
    // 真正有用的设置,要到递归到内层(server block和location block)时才会做
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;

    // 先保存上层ctx,保持其“纯洁性”。nginx这一套配置的层次设计所要求的,每次的结构都一样,
    // 但是具体的信息不同,也就是说,在server和location的解析中每个层次都有自己的ngx_http_conf_ctx_t结构
    // 外层只是一个架子,内层会针对具体配置来填充自己的ngx_http_conf_ctx_t结构中src_conf,loc_conf的项目。
    saved = *ctx;
    rv = NGX_CONF_OK;

    for (s = 0; s < cmcf->servers.nelts; s++) {
  
        ctx->srv_conf = cscfp[s]->ctx->srv_conf;

        if (module->merge_srv_conf) {
            /*
            * saved.srv_conf是上层srv_conf的数组,cscfp[s]>ctx->srv_conf是下层srv_conf的组数,他们都包含了
            * 各个module中srv_conf,ctx_index就是某个具体的module在srv_conf数组中的下标,通过这个下标
            * 就可以拿到该module的srv_conf.那么一个上层的一个下层的,要做什么呢?这里以ngx_http_core_merge_srv_conf
            * 函数为例,看看它的原理是什么,loc_conf的处理是一样的,这里就不介绍了。
            */
            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
                                        cscfp[s]->ctx->srv_conf[ctx_index]);
            .......
        }
        .....

    return rv;
}
下面摘录下ngx_http_core_merge_srv_conf的部分代码:
ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_core_srv_conf_t *prev = parent; // 上层
    ngx_http_core_srv_conf_t *conf = child;    // 下层

    ngx_conf_merge_size_value(conf->connection_pool_size,
                              prev->connection_pool_size, 256);
   ....
}
关于这个宏的解释:
/* 
* 意思很明确,如果下层的某个变量没有配置,那么就用上层(若有设置的话)的,因为我们在使用srv_conf或者
* loc_conf的时候一般都是要用到底层的,也就是具体请求对应的location的配置,很多srv_conf的配置是需要传递下来
* 供下层使用的,(main_conf底层跟上层都是共享的)
*/
#define ngx_conf_merge_size_value(conf, prev, default)                       \
    if (conf == NGX_CONF_UNSET_SIZE) {                                       \
        conf = (prev == NGX_CONF_UNSET_SIZE) ? default : prev;               \
}


以上的分析是否是将前面提到的论点讲述清楚了呢?这就是nginx的merge动作的实质。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值