静态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;
}