nginx配置解析之配置合并

        上一篇文章分析了nginx.conf配置解析流程,解析完成后会把各个配置项存放到各个模块的上下文结构中。但此时还没有对http模块、server模块、location模块公共部分进行合并处理。所谓的合并: server块的模块上下文没有值,则继承http模块的模块上下文值。location块的模块上下文没有值,则继承server块模块上下文的值。接下来分析nginx是如何合并http模块、server模块、location模块公共部分。

        假设nginx.conf配置文件结构如下

http
{	
	//server块1
	server
	{
		//location块1
		location
		{
		
		}
		//location块2
		location
		{
		
		}
	}
	//server块2
	server
	{
	
	}
}
        这是nginx.conf配置文件的一个框架结构,其中省略了其他配置项。http模块下有两个server块。其中第一个server块下还有两个location块。解析配置后,http模块的上下文结构如下图:

        http块下有两个server块,分别为server块1,server块2。这两个server块是通过数组形式连接起来。http块中的main_conf[0]核心模块上下文结构为ngx_http_core_main_conf_t,它的成员servers就是一个数组,存放这这两个server块。

        ngx_http_core_loc_conf_s结构中的成员locations是一个队列,队列元素为某个server块下的各个location结构。图中server块1下有两个location块,server1块loc_conf中的核心模块上下文结构的ocations,是由这两个location块组成的队列。

        也就是说server块是通过数组串接起来的, location块是通过链表串接起来的。

一、http块与server块的合并

        http块与server块的合并过程分析:包含server块的合并,location块的合并。

        (1)server块的合并: 对于每一个模块,在每一个server块中,找到模块在srv_conf中的位置,然后将该模块上下文与http块中srv_conf对应模块所在位置模块上下文进行比较。如果server块中的上下文没有值,则使用http上下文的值,否则使用server块中模块上下文自己的值。以ngx_core_module模块为例,这个模块是第一个模块,存放在srv_conf下标为0的位置。首先将server1块中的srv_conf[0]与http块的srv_conf[0]进行合并, 然后将server2块中的srv_conf[0]与http块的srv_conf[0]进行合并。这样server块的合并就完成了。

        (2)location块的合并: 对于每一个模块,在每一个server块中,找到模块在loc_conf中的位置,然后将该模块上下文与http块中loc_conf对应模块所在模块上下文进行比较。如果location块中的上下文没有值,则使用http上下文中的值,否则使用location块中模块上下文自己的值。以ngx_core_module模块为例,这个模块是第一个模块,存放在loc_conf下标为0的位置。首先将server1块中的loc_conf[0]与http块的loc_conf[0]进行合并, 然后将server2块中的lco_conf[0]与http块的loc_conf[0]进行合并。这样loc块的合并就完成了。

char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    for (m = 0; ngx_modules[m]; m++) 
	{
        if (ngx_modules[m]->type != NGX_HTTP_MODULE) 
		{
            continue;
        }
		//(1)将http中的server与server块的server合并
		//(2)将http中的loction与server块的location合并
		//(3)将server块中的location与localtion中的location合并
        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
    }
}
        而其中的函数ngx_http_merge_servers负责具体的合并过程。这个函数一共使用了3个合并过程,先分来http块与server的合并。

//cmcf = ctx->main_conf[ngx_http_core_module.ctx_index],其中ctx是http块的ngx_http_conf_ctx_t结构
//module指的是模块上下文
//ctx_index指的是该模块在同一类型中的位置
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)
{
	//cscfp指向所有http块下的所有server块
    cscfp = cmcf->servers.elts;
	//ctx指向http块的ngx_http_conf_ctx_t结构
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;  
	//遍历http块下有所有server块
    for (s = 0; s < cmcf->servers.nelts; s++) 
	{
		//指向每一个server块中的srv_conf结构
        ctx->srv_conf = cscfp[s]->ctx->srv_conf;
        if (module->merge_srv_conf) 
		{
			//将http块中的某个server与server块中的某个server进行合并
			//saved.srv_conf[ctx_index]是http块下的srv_conf中某个元素
			//cscfp[s]->ctx->srv_conf[ctx_index]是server块下的srv_conf中某个元素
            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index], cscfp[s]->ctx->srv_conf[ctx_index]);
         
        }

        if (module->merge_loc_conf) 
		{
            ctx->loc_conf = cscfp[s]->ctx->loc_conf;
			//将server块中loc_conf的某个loc与http块中loc_conf的某个loc合并
            rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],  cscfp[s]->ctx->loc_conf[ctx_index]);
        }
    }
}
二、server块与location块的合并
        server块与location块合并的内容就比较少了,只需要将各个location块中的loc_conf与server块中的loc_conf进行合并。

        location块的合并: 对于每一个模块,在每一个location块中,找到模块在loc_conf中的位置,然后将该模块上下文与所属server块中loc_conf对应模块所在模块上下文进行比较。如果location块中的上下文没有值,则使用所属server块上下文中的值,否则使用location块中模块上下文自己的值。以ngx_core_module模块为例,这个模块是第一个模块,存放在loc_conf下标为0的位置。首先将location1块中的loc_conf[0]与server块1的loc_conf[0]进行合并, 然后将locatio2块中的lco_conf[0]与server1块的loc_conf[0]进行合并。这样loc块的合并就完成了。


        函数ngx_http_merge_locations负责server块与location块的合并。当然如果location还嵌套location块,则会递归合并location块与location内的所有子locaton块。

//locations为server块中ngx_http_core_module的lociton中队列
//loc_conf为server块的loc_conf
//module为模块上下文
//ctx_index指module对应模块在同一类模块中的索引
static char * ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
{
    for (q = ngx_queue_head(locations);
         q != ngx_queue_sentinel(locations);
         q = ngx_queue_next(q))
    {
		//合并server块与locatin块中相应的location
		//loc_conf[ctx_index]为server块中loc_conf的某个loc
		//clcf->loc_conf[ctx_index]为location块中的loc_conf的某个loc
        rv = module->merge_loc_conf(cf, loc_conf[ctx_index], clcf->loc_conf[ctx_index]);

		//递归合并location块下的location
		//clcf->locations为location块中的loc_conf某个loc对应的队列
		//clcf->loc_conf为location块中的loc_conf
        rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf, module, ctx_index);
    }
}
        最终ngx_core_module模块的合并结果如下:


        以上只是ngx_core_module模块的合并结果,其它模块合并的过程也是一样的。最终一个for循环,就可以合并所有http模块。这样每一个http模块的上下文结构都有值,这个值要么来自nginx.conf配置文件,要么继承上一层结构。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Nginx配置文件是用来配置Nginx服务器的行为和功能的文件。配置文件通常位于Nginx安装目录下的`conf`文件夹中,主要有两个文件:`nginx.conf`和`sites-available/default`。其中,`nginx.conf`是主配置文件,而`sites-available/default`是默认的虚拟主机配置文件。 在Nginx配置文件中,可以设置一些全局的参数,如`worker_processes`用于指定Nginx的工作进程数,`events`用于配置事件模块,`http`用于配置HTTP模块等。此外,还可以使用`include`指令来引入其他配置文件,以便更好地组织和管理配置配置文件中的每个指令都有特定的作用,比如`pid`指令用于指定Nginx进程的PID存放路径,`location`指令用于URL地址匹配,可以实现对动态和静态网页的过滤处理,也可以用于实现反向代理和负载均衡等功能。 总之,Nginx配置文件是用来定义Nginx服务器的行为和功能的重要文件,通过对配置文件的修改和调整,可以实现对Nginx服务器的灵活配置和定制。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [Nginx配置文件解析及功能演示](https://blog.csdn.net/pokes/article/details/121979187)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Nginx配置文件详解](https://blog.csdn.net/qq_41536778/article/details/104726671)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值