设为首页 收藏本站
查看: 687|回复: 0

[经验分享] 关于nginx配置解析中merge操作的探讨

[复制链接]

尚未签到

发表于 2016-12-28 07:26:58 | 显示全部楼层 |阅读模式
我们先来看看http module的类型的结构体:

typedef struct {

ngx_int_t (*preconfiguration)(ngx_conf_t *cf);

ngx_int_t (*postconfiguration)(ngx_conf_t *cf);


void *(*create_main_conf)(ngx_conf_t *cf);

char *(*init_main_conf)(ngx_conf_t *cf, void *conf);


void *(*create_srv_conf)(ngx_conf_t *cf);

char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);


void *(*create_loc_conf)(ngx_conf_t *cf);

char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);

} ngx_http_module_t;




   中间有两项被加粗的成员,这就是要讨论的重点了,其他的项都好说,这里有点不太明确的就是preconfiguration

和postconfiguration,这两个handler的一般作用分别是:

preconfiguration:设置一些全局预定义的变量,在之后的解析中可能要用到

postconfiguration: 字如其名,一般是在配置解析完之后,设置一些处理handler或者filter handler




关于merge,中文翻译一般为:合并,那么谁跟谁合并,为什么要合并,就是我们要讨论的问题!

这里先交代一个背景,关于nginx的配置信息组织结构。

http

  |__server

  |   |__location

  |   |__location

  |

  |__server

     |__location




nginx每当解析一个server或者location是都以一个ctx(类型是ngx_http_conf_ctx_t),即所谓的上下文变量来保存

当前(即局部)的配置,同时上层的ctx可以从cf->ctx的形式得到,在这个当前ctx中它的main_conf会继承上层,这点上

server和location是一样的处理,而若当前是server,那么它ctx中的src_conf和loc_conf需要重新创建,而location处理时,

则只会创建loc_conf,src_conf共享上层server的。  




函数ngx_http_merge_servers:

static char *
ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
ngx_http_module_t *module, ngx_uint_t ctx_index)
{
char                        *rv;
ngx_uint_t                   s;
ngx_http_conf_ctx_t         *ctx, saved;
ngx_http_core_loc_conf_t    *clcf;
ngx_http_core_srv_conf_t   **cscfp;
// http block中配置的server块,都放在cmcf->servers这个数组中
cscfp = cmcf->servers.elts;
// 在外层的处理中cf->ctx的main_conf,srv_conf和loc_conf都已初始化过了
// 但是大部分都是空壳,即简单的create,没有有针对配置的具体指令来设置
// 真正有用的设置,要到递归到内层(server block和location block)时才会做
ctx = (ngx_http_conf_ctx_t *) cf->ctx;
// 先保存上层ctx,保持其“纯洁性”。nginx这一套配置的层次设计所要求的,每次的结构都一样,
// 但是具体的信息不同,也就是说,在server和location的解析中每个层次都有自己的ngx_http_conf_ctx_t结构
// 外层只是一个架子,内层会针对具体配置来填充自己的ngx_http_conf_ctx_t结构中src_conf,loc_conf的项目。
saved = *ctx;
rv = NGX_CONF_OK;
for (s = 0; s < cmcf->servers.nelts; s++) {
ctx->srv_conf = cscfp->ctx->srv_conf;
if (module->merge_srv_conf) {
/*
* saved.srv_conf是上层srv_conf的数组,cscfp>ctx->srv_conf是下层srv_conf的组数,他们都包含了
* 各个module中srv_conf,ctx_index就是某个具体的module在srv_conf数组中的下标,通过这个下标
* 就可以拿到该module的srv_conf.那么一个上层的一个下层的,要做什么呢?这里以ngx_http_core_merge_srv_conf
* 函数为例,看看它的原理是什么,loc_conf的处理是一样的,这里就不介绍了。
*/
rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
cscfp->ctx->srv_conf[ctx_index]);
.......
}
.....
return rv;
}

下面摘录下ngx_http_core_merge_srv_conf的部分代码:

ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_core_srv_conf_t *prev = parent; // 上层
ngx_http_core_srv_conf_t *conf = child;    // 下层
ngx_conf_merge_size_value(conf->connection_pool_size,
prev->connection_pool_size, 256);
....
}关于这个宏的解释:

/*
* 意思很明确,如果下层的某个变量没有配置,那么就用上层(若有设置的话)的,因为我们在使用srv_conf或者
* loc_conf的时候一般都是要用到底层的,也就是具体请求对应的location的配置,很多srv_conf的配置是需要传递下来
* 供下层使用的,(main_conf底层跟上层都是共享的)
*/
#define ngx_conf_merge_size_value(conf, prev, default)                       \
if (conf == NGX_CONF_UNSET_SIZE) {                                       \
conf = (prev == NGX_CONF_UNSET_SIZE) ? default : prev;               \
}






以上的分析是否是将前面提到的论点讲述清楚了呢?这就是nginx的merge动作的实质。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-320308-1-1.html 上篇帖子: nginx配置文件实例: php (fastcgi), perl, proxy, rrd, nagios 下篇帖子: nginx rewrite伪静态配置参数详细说明
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表