当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{},它们之间的关系用下图能够清晰的说明:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbmVzdGxlcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">


以下介绍解析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.

最新文章

  1. 前端学PHP之PHP操作memcache
  2. 拖动对象ondrag
  3. ubuntu 系统下搭建Java的环境
  4. Linux下查看版本号,查看存在的普通用户
  5. Neo4j创建自动索引
  6. Coursera Machine Learning : Regression 多元回归
  7. SQL Server时间粒度系列----第2节日期、周时间粒度详解
  8. JS事件冒泡
  9. CocoaPod出现-bash: pod: command not found 解决办法
  10. 【云计算】Dockerfile示例模板
  11. CSS-Transform-transition-Animation
  12. 外部表查询时出现ORA-29913和ORA-29400错误
  13. apache开源项目--Sirona
  14. Android主题切换方案总结
  15. C++文件
  16. Stripe
  17. Android开发——使用高级的RecyclerView实现侧滑菜单删除功能(SwipeRecyclerView)
  18. jquery四种监听事件的区别
  19. python接口自动化(二十三)--unittest断言——上(详解)
  20. C# 解析torrent文件

热门文章

  1. Cow Navigation(USACO)
  2. ANDROID开发笔记(二)
  3. openshift 云平台基于kubernetes
  4. hdu 1102(最小生成树)
  5. 牛客网 暑期ACM多校训练营(第二场)J.farm-STL(vector)+二维树状数组区间更新、单点查询 or 大暴力?
  6. jmeter引用cookies进行登录实战
  7. Walls and Gates -- LeetCode
  8. (转)Unity3D 开发优秀技术资源汇总
  9. InputSplit—>RecordReder—>map(key,value,context)的过程解析
  10. Ubuntu 16.04桌面版GUI网络配置工具NetworkManager的命令行工具nm-tool无法使用的问题