【Nginx】HTTP配置模型

当Nginx检測到配置文件里存在配置块http{}时。会建立一个ngx_http_conf_ctx_t结构体,该结构体定义例如以下:

typedef struct {
    void        **main_conf;    // 每一个指针元素指向全部由HTTP模块的create_main_conf方法产生的结构体
    void        **srv_conf;     // 每一个指针元素指向全部由HTTP模块的create_srv_conf方法产生的结构体
    void        **loc_conf;     // 每一个指针元素指向全部由HTTP模块的create_loc_conf方法产生的结构体
} ngx_http_conf_ctx_t;


详细来说,框架代码在遇到http{}时会调用核心模块ngx_http_module(HTTP框架的一部分)中解析配置项的ngx_http_block方法,该方法的关于生成和配置ngx_http_conf_ctx_t结构体的过程大致例如以下,代码位于ngx_http.c中:
ngx_http_conf_ctx_t  *ctx;     // 定义一个该结构体的指针
 
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));     // 分配该结构体空间

ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);     // 分配数组存放指针
ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);      // 分配数组存放指针
ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);      // 分配数组存放指针
 
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;
 
    if (module->create_main_conf)
    {
        /* 依次调用全部HTTP模块的create_main_conf方法
         * 产生的结构体指针放入上面分配了空间的main_conf指针数组中
         */
        ctx->main_conf[mi] = module->create_main_conf(cf);
        if (ctx->main_conf[mi] == NULL)
        {
            return NGX_CONF_ERROR;
        }
    }
 
    if (module->create_srv_conf)
    {
        /* 依次调用全部HTTP模块的create_srv_conf方法
         * 产生的结构体指针放入上面分配了空间的srv_conf指针数组中
         */
        ctx->srv_conf[mi] = module->create_srv_conf(cf);
        if (ctx->srv_conf[mi] == NULL)
        {
             return NGX_CONF_ERROR;
        }
    }
 
    if (module->create_loc_conf)
    {
        /* 依次调用全部HTTP模块的create_loc_conf方法
         * 产生的结构体指针放入上面分配了空间的loc_conf指针数组中
         */
        ctx->loc_conf[mi] = module->create_loc_conf(cf);
        if (ctx->loc_conf[mi] == NULL)
        {
            return NGX_CONF_ERROR;
        }
    }
}


server{}和location{}和http{}相似:
  • 当遇到server{}配置块时,建立ngx_http_conf_ctx_t结构体。main_conf成员指向父配置块所相应的ngx_http_conf_ctx_t结构体,srv_conf成员和loc_conf成员存储HTTP模块通过create_srv_conf和create_loc_conf方法产生的配置结构体指针。
  • 当遇到location{}配置块时,建立ngx_http_conf_ctx_t结构体,main_conf成员指向父配置块相应ngx_http_conf_ctx_t结构体。srv_conf成员指向父配置块ngx_http_conf_ctx_t结构体的srv_conf元素。loc_conf存储HTTP模块create_loc_conf方法产生的配置结构体指针。
三个ngx_http_conf_ctx_t结构体分别相应http{}、server{}、location{},它们之间的关系用下图能够清晰的说明:


以下介绍解析HTTP配置的大致流程:
  1. Nginx进程主循环调用配置文件解析器解析nginx.conf配置文件。
  2. 配置文件解析器发现http{},启动HTTP框架,也就是核心模块ngx_http_module。

  3. 核心模块调用ngx_command_t中的set回调函数,也就是ngx_http_block方法。

  4. 初始化全部HTTP模块的序号。分配一个ngx_http_conf_ctx_t结构体并初始化三个数组。

  5. 调用每一个HTTP模块的create_main_conf、create_srv_conf、create_loc_conf方法分配存储配置项參数的结构体,返回的指针保存在ngx_http_conf_ctx_t结构体中。
  6. 调用每一个HTTP模块的preconfiguration方法。

  7. 配置文件解析器检測到一个配置项后。遍历全部HTTP模块的ngx_command_t数组,看有没有可以和配置项名称匹配的ngx_command_t结构体,有则调用ngx_command_t结构中的set方法来处理配置项。

  8. 配置文件解析器继续检測配置项,遇到server{}或location{}则以类似的方法递归解析块中的配置项,只是此时负责解析配置项的模块变成了ngx_http_core_module,方法在上面已经具体说明了。

  9. 配置文件解析器解析到http{}尾端,返回HTTP框架ngx_http_module。
  10. 调用merge_srv_conf和merge_loc_conf等方法合并配置项结构体。

  11. HTTP框架处理完http配置项,ngx_command_t的set回调方法返回。
  12. 配置文件解析器返回Nginx主循环。Nginx进程启动Web服务器。
參考:
《深入理解Nginx》 P140-P143.
原文地址:https://www.cnblogs.com/yxysuanfa/p/7243842.html