nginx配置解析原理(三)

在前一篇文章(二)中我们说到了"server"指令的解析过程,并且知道了每遇到一个"server"时便会创建一个ngx_http_conf_ctx_t结构,初始化该结构并且将其放在一个特定数组中。然后开始对server{...}内部指令开始解析,本文主要就来描述server块内部的解析流程。

对于server{...}内部的指令解析的原理其实也比较简单:同样是对每个指令执行"加载-匹配-设置"的循环往复。但是由于server{...}内部可能嵌套location... {...}块,因此一切也就变得不太一样了,因此,本文重点描述对于"loc"指令的解析。

"location"指令是由ngx_http_core_module负责解析,而解析函数是ngx_http_core_location

ngx_http_core_location

首先我们来简单看看这个函数被调用时的上下文(由于"location"是出现在server{...}配置块中,因此,调用者的上下文设置是在函数ngx_http_core_server中设置):
static char *
ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
    ......
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_SRV_CONF; 
    ......
}
接下来再看看ngx_http_core_location的解析过程:
static char *
ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

    pctx = cf->ctx;
    ctx->main_conf = pctx->main_conf;
    ctx->srv_conf = pctx->srv_conf;

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }
    for (i = 0; ngx_modules[i]; i++) {
        if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = ngx_modules[i]->ctx;

        if (module->create_loc_conf) {
            ctx->loc_conf[ngx_modules[i]->ctx_index] =
                                                   module->create_loc_conf(cf);
            if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) {
                 return NGX_CONF_ERROR;
            }
        }
    }
    ......
    pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
    ......
    if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    save = *cf;
    cf->ctx = ctx;
    cf->cmd_type = NGX_HTTP_LOC_CONF;

    rv = ngx_conf_parse(cf, NULL);

    *cf = save;

    return rv;
对于location指令的解析的主要完成了如下工作:
  1. 分配ctx = ngx_http_conf_ctx_t结构来代表location {...},后面我们会看到这个配置块非常重要;
  2. 将ctx->main_conf和ctx->srv_conf分别设置为父配置块的main_conf以及srv_conf,同时为ctx->loc_conf分配内存空间用以存储location {...}配置块内的指令配置;
  3. 调用每个http模块的create_loc_conf回调,初始化2中的loc_conf数组(void *)数组
  4. 接下来是重点:pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]:通过这个来获取父配置块(代表location指令所属的server{...}的ngx_http_conf_ctx_t)的http_core_module的loc_conf配置pclcf,我们下面会使用该结构的locations成员;
  5. 调用ngx_http_add_location(cf, &pclcf->locations, clcf)来将该location块的ngx_http_conf_ctx_t结构添加至pclcf->locations队列中,这样,每个server就可以通过该结构来管理下面的所有location配置;
  6. 完成了上面 的主要解析工作以后,我们还需要进入location ... {...}块内部进行解析,在解析前我们需要知道此时上下文环境已经发生了变化,因此,需要重新设置:cf->ctx = ctx; cf->cmd_type = NGX_HTTP_LOC_CONF;
我想,下图能够比较清晰地表达出server配置块的数据结构和location配置块数据结构之间的关系:

有一个疑问:我真的理解了ngx_http_conf_ctx_t中各个成员变量的含义了吗?显然没有,比如:代表server {...}配置块的ngx_http_conf_ctx_t的结构的loc_conf的真正含义到底是什么?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值