Nginx源码初探之HTTP模块 -HTTP框架初始化流程

静态HTTP框架启动流程
       Nginx模块化设计使得每个HTTP模块都可以专注于完成一个独立的、简单的功能,而一个请求的完整处理过程可以由无数个HTTP模块共同完成。依照常规的HTTP处理流程,Nginx将这些HTTP模块分为11个处理阶段。Nginx框架的初始化工作主要就是解析nginx.conf并且将这11个处理阶段依照顺序和相应的模块关联起来。

1.HTTP模块配置介绍
        HTTP配置管理包括全局配置项(main_conf)、server配置项(srv_conf)、location配置项(loc_conf).由于HTTP模块具有3种不同级别的配置项,所以管理要复杂的多。对于HTTP框架而言,任何一个HTTP模块的server配置项都可能出现在main级别中,location配置项可能出现在main和srv级别中。
2.HTTP处理阶段。 
       Nginx模块化设计使得每个HTTP模块都可以专注于完成一个独立的、简单的功能,而一个请求的完整处理过程可以由无数个HTTP模块共同完成。依照常规的HTTP处理流程,Nginx将这些HTTP模块分为11个处理阶段。Nginx框架的初始化工作主要就是解析nginx.conf并且将这11个处理阶段依照顺序和相应的模块关联起来。
对于这11个处理阶段,有些事必备的,有些事可选的(暂时不用关注具体是哪些阶段,后续我们会专门介绍)。
3.HTTP框架启动流程
       首先完整的介绍HTTP框架的初始化所以,一篇文章是不可能的,我发现那个不符合我理解事物,描述事物的思维逻辑。这里我们主要关注ngx_http_module初始化的过程。这个方法基本上包括了HTTP框架的完成初始化流程。
Nginx模块设计是层级化得,核心模块管理非核心模块。HTTP框架的初始化主要就是初始化HTTP模块的功能,实现在ngx_http_module核心模块中。总的来说分为三个步骤第一个步骤初始化配置,第二步初始化HTTP模块,第三步设置监听端口和服务列表。

1.为全局配置,serve配置,location配置分配内存空间
2.为所有的模块创建main_conf's和空的srv_conf's和空的loc_conf's
3.配置文件(nginx.conf)解析,初始化main_conf's合并srv_conf's和loc_conf's
4.构筑location组成的静态二叉平衡查找树
5.调用HTTP模块的postconfiguration方法使之介入 HTTP阶段
6.初始化模块的handler数组
8.构造server虚拟主机构成的支持通配符的散列表
9.构造监听端口与server间的关联关系

4.初始化源码

HTTP框架初始源码在ngx_http_module的ngx_http_block中,参照源码可以看的更清楚直观一些。

static char *
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    char                        *rv;
    ngx_uint_t                   mi, m, s;
    ngx_conf_t                   pcf;
    ngx_http_module_t           *module;
    ngx_http_conf_ctx_t         *ctx;
    ngx_http_core_loc_conf_t    *clcf;
    ngx_http_core_srv_conf_t   **cscfp;
    ngx_http_core_main_conf_t   *cmcf;

    if (*(ngx_http_conf_ctx_t **) conf) {
        return "is duplicate";
    }

    /* 1.为mainhttp contex分配内存空间*/

    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
    if (ctx == NULL) {
        return NGX_CONF_ERROR;
    }

    *(ngx_http_conf_ctx_t **) conf = ctx;


    /* 2.统计模块数量并设置模块编号,这个编号也用于后续创建配置文件的排序。 */

    ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE);

    /*3.分配配置空间*/
    /* 3.1创建main_conf 数组,所有模块按照http请求处理顺序和main_conf中编号保持一致 */

    ctx->main_conf = ngx_pcalloc(cf->pool,
                                 sizeof(void *) * ngx_http_max_module);
    if (ctx->main_conf == NULL) {
        return NGX_CONF_ERROR;
    }


    /*
     * 3.2创建空的loc_conf上下文,用于合并servers' srv_conf's
     */

    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->srv_conf == NULL) {
        return NGX_CONF_ERROR;
    }


    /*
     *3.3创建空的loc_conf上下文,用于合并servers' loc_conf  
     */

    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
    if (ctx->loc_conf == NULL) {
        return NGX_CONF_ERROR;
    }


    /*
     * 4.为所有模块初始化main_conf,srv_conf.loc_conf
     */

    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }
        /*4.1获取模块编号*/
        module = cf->cycle->modules[m]->ctx;
        mi = cf->cycle->modules[m]->ctx_index;
        /*4.2.调用create_main_conf为模块初始化main_conf*/
        if (module->create_main_conf) {
            ctx->main_conf[mi] = module->create_main_conf(cf);
            if (ctx->main_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }
        /*4.3.调用create_srv_conf为模块初始化srv_conf*/
        if (module->create_srv_conf) {
            ctx->srv_conf[mi] = module->create_srv_conf(cf);
            if (ctx->srv_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }
          /*4.4.调用create_loc_conf为模块初始化loc_conf*/
        if (module->create_loc_conf) {
            ctx->loc_conf[mi] = module->create_loc_conf(cf);
            if (ctx->loc_conf[mi] == NULL) {
                return NGX_CONF_ERROR;
            }
        }
    }

    pcf = *cf;
    cf->ctx = ctx;
    /*5.调用所有HTTP模块的preconfiguration,使其可以加入HTTP阶段*/
    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;

        if (module->preconfiguration) {
            if (module->preconfiguration(cf) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }
    }

    /*6. 解析配置文件中http配置块的内容,配置文件赋值 */

    cf->module_type = NGX_HTTP_MODULE;
    cf->cmd_type = NGX_HTTP_MAIN_CONF;
    rv = ngx_conf_parse(cf, NULL);

    if (rv != NGX_CONF_OK) {
        goto failed;
    }

    /*
     *7.配置文件(nginx.conf)解析,初始化main_conf's合并srv_conf's和loc_c*onf's
     */

    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
    cscfp = cmcf->servers.elts;
/*HTTP框架将HTTP请求分为11个阶段,其中7个是HTTP模块需要加入HTTP处理阶段,这里只处理这7个阶段*/
    for (m = 0; cf->cycle->modules[m]; m++) {
	   
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;
        mi = cf->cycle->modules[m]->ctx_index;

        /* 7.1解析nginx.conf中http{}配置,并逐一初始化每个模块的main.conf */

        if (module->init_main_conf) {
            rv = module->init_main_conf(cf, ctx->main_conf[mi]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }
       /* 7.1合并server配置 */
        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
        if (rv != NGX_CONF_OK) {
            goto failed;
        }
    }


    /* 8.构建location的红黑树 */

    for (s = 0; s < cmcf->servers.nelts; s++) {

        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

        if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }

        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }


    if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }


    for (m = 0; cf->cycle->modules[m]; m++) {
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = cf->cycle->modules[m]->ctx;

        if (module->postconfiguration) {
            if (module->postconfiguration(cf) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }
    }

    if (ngx_http_variables_init_vars(cf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    /*
     * http{}'s cf->ctx was needed while the configuration merging
     * and in postconfiguration process
     */

    *cf = pcf;


    if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }


    /* 9.optimize the lists of ports, addresses and server names 
	创建server服务的监听散列表*/

    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;

failed:

    *cf = pcf;

    return rv;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值