您的位置:首页 > 运维架构 > Nginx

nginx 配置解析(11)——merge

2015-06-05 18:03 1001 查看
以前我们详细了分析了 nginx 配置解析的各个过程,尤其是各种 conf 结构的创建、初始化、储存。那么现在我们要分析下 merge 的过程,一来它确实是配置解析过程的一个部分,二来我们可以检验下我们对各种 conf 结构存储的位置是否真正的清晰明了。

首先我们了解下 merge 的背景:

所谓 merge 操作,就是合并内外层的配置。大体原则是:如果内层没有配置,那么以外层为准,如果都没有配置,那么就用默认值;
NGX_CORE_MODULE 模块的 ctx(ngx_core_module_t)是没有 merge 操作的,所以像 http 块这一层的配置是不需要和上一层去 merge 的,想想也明白为什么,http 哪来的上一层呢?
NGX_HTTP_MODULE 模块的 ctx(ngx_http_module_t)是有 merge 操作的,但是仅仅有 merge_srv_conf 和 merge_loc_conf,同理对 main 层不需要 merge;
merge 操作发生的时机是在 ngx_http_block函数中(即 http 块解析函数),在递归调用 ngx_conf_parse 之后。这是为了让 http 块之内所有的指令都解析结束,然后再去做 merge 操作;
不同层级块的逻辑关系,基本上都是放在 ngx_http_core_module 这个模块的不同级别的 conf 中,在 merge 中会频繁用到。

来看看 ngx_http_block 中的一段:

再明显不过了,init 了 main,merge 了 server。 这里的处理流程是个 for 循环,每次的迭代对象是模块本身,也就是挨个模块的去处理 merge。

在进入 ngx_http_merge_servers 内部分析之前,我们先确认一下这些代入的参数:

cf 是代入的参数,但是我们真正关心的还是 cf->ctx,这个时候它其实就是 http 块的三元组(代入 ngx_http_block 的时候还不是,但是在函数中赋值了);
cmcf 这个 http 块的 ngx_http_core_module 的 main_conf 结构;
module 是个循环获取的,代表当前模块;
mi 就是当前模块在 NGX_HTTP_MODULE 模块中的 index;

这里很奇怪的就是并没有明确指出 merge loc_conf 的地方,我们推测它是在 ngx_http_merge_servers 中实现的,那么我们具体的分析下它的代码:

在这个函数中分别对 srv_conf 和 loc_conf 做了 merge 操作,用 http 块创建的 srv_conf 和 loc_conf 作为外层,用 server 块创建的 srv_conf 和 loc_conf 作为内层。但是考虑到这不是终结,还需要继续深入到 location 中继续 merge,所以要把 cf->ctx 的内容做修改,不断的用内层内容覆盖再继续去 merge,所以重点关注下
cf->ctx 内容的改变。当然在函数最后结束的时候,还需要恢复 cf->ctx 的值。

那么下一步我们需要分析一下 ngx_http_merge_locations 函数,这个函数负责各个 location 块的 merge。同样的,在分析它之前,先想想上下文环境:

在 ngx_http_merge_servers 中 cf->ctx 中的 srv_conf 和 loc_conf 都被改成当前 server 对应的 conf 结构了,明显是为了进一步 merge 做准备;
从 ngx_http_merge_servers 中进入 ngx_http_merge_locations 的 clcf 就是从 server 块 ngx_http_core_module 的 loc_conf;
location 是可以嵌套的,那么嵌套关系的内外层 location 是否也会 merge 呢?

我们来分析 ngx_http_merge_locations 的代码吧:

这里唯一值得注意的就是那个递归调用,这里成功的解决了 location 嵌套的 merge 问题。

总结一下重点吧:

在 ngx_http_block 中调用 ngx_http_merge_servers 去 merge 对应的 srv_conf;
在 ngx_http_merge_servers 和 ngx_http_merge_locations 中调用 ngx_http_merge_locations 去 merge 对应的 loc_conf;
在内存上,注意内外层关系,仔细阅读代码,看看内外级关系的内存是如何处理的;
cf->ctx 在一层层的 merge 中也起到了至关重要的作用,到了内层 merge 的时候,它存的总是逻辑上的直接外层三元组。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: