nginx源码分析--配置结构体在内存中的分布

1httpmodule的配置结构体的组织结构

Nginx中,http类的module允许创建3种配置结构体:main_confsrv_confloc_conf,分别通过create_main_confcreate_srv_confcreate_loc_conf钩子创建。每种配置结构体的指针存储在对应的指针数组中,以ctx_index为数组下标。见下图所示。

ngx_http_conf_ctx_t变量的指针ctx存储在cycleconf_ctx所指向的指针数组,以ngx_http_moduleindex为下标的数组元素。

这是http配置结构体的最初结构,在配置了server{}location{}的情况下,http的配置结构体的组织结构将变得复杂起来。

下面是ngx_http_core_module的配置结构体,这是很重要的数据结构。

ngx_http_core_main_conf_tngx_http_core_modulemain_conf,存储了http层的配置参数和http的处理引擎。

ngx_http_core_srv_conf_tngx_http_core_modulesrv_conf,存储了server层的配置参数。

ngx_http_core_loc_conf_tngx_http_core_moduleloc_conf,存储了location层的配置参数。

从配置文件我们可以看到,http层、server层、location层的配置是嵌套结构的,所以程序的内部与之对应的配置结构体之间也具有对应的层次结构。

2ngx_http_core_modulesrv_conf的组织结构

ngx_http_block()解析到“server”指令时会调用其set钩子ngx_http_core_server(),开始构建ngx_http_core_modulesrv_conf

每个“server”指令都会创建一个上图的server框中的部分,其空间是从函数参数cfpool中分配的,ngx_http_core_srv_conf_t的指针存储到ngx_http_core_main_conf_tarray容器servers中。

图中server部分的ngx_http_conf_ctx_t中的srv_confloc_conf也要分配空间并执行每个http类的modulecreate_srv_confcreate_loc_conf钩子。

3ngx_http_core_moduleloc_conf的组织结构

创建完上面的数据结构后,就解析这个“server{}”中的指令,当解析到location”指令时会调用其set钩子ngx_http_core_location()

“server{}”中的每个“location”都会构建上图中的location框中的数据结构,并按照在配置文件中出现的顺序通过ngx_http_location_queue_t中的双向链字段queue建立起链关系。图中exactinclusive的虚线表示实际只有一条线,要根据实际上“location”指令的配置:如果location是精确匹配、正则表达式、@命名则exact字段有效,否则就是inclusive字段有效。

ngx_http_core_location()创建完上面的数据结构后,就解析这个“location{}”中的指令。如果这个“locatin{}”嵌套了“location{}”,则还是调用ngx_http_core_location(),只不过此时的cf->ctx是上图中的ctx’,嵌套的location按照以上的方法挂到dummylocations下,同样也体现了层次结构。

4ngx_http_core_moduleloc_conf的组织结构的优化调整

在解析指令过程中创建的location的数据结构通过双向链建立起关系,这个双向链结构是临时的,从代码中也可以看出,双向链的节点(即ngx_http_location_queue_t节点)都是在temp_pool临时内存池中分配空间。

创建location的组织结构的目的无非就是当http请求到达后根据uri查找到合适的location,以便使用其配置完成处理。上述简单的链式结构对于遍历查找location的效率不高,所以Nginx需要设计高效的数据结构来检索location

所以,在完成所有配置指令后,就调用ngx_http_init_locations()ngx_http_init_static_location_trees()来调整location的组织结构(其实只是将读取配置过程形成的双向链结构调整成相应的组织结构,location本身没有任何改变)。

看看ngx_http_init_locations()

先对双向链中的location进行排序,顺序为:exactinclusive(排序,如果exactlocation名字和inclusive的相同,则exact排在前面–> regex(未排序)–> named(字典序排序–> noname(未排序)

然后遍历链表,得出regex类型的首节点和节点个数rnamed类型的首节点和节点个数n以及noname类型的首节点。

如果存在noname首节点就将双向链表从noname首节点处断开。

如果存在named首节点,就分配n+1的指针数组,并依次将named类型的location的指针(在链节点的exact字段)存储到指针数组中,数组的最后一个元素置为空指针,servernamed_locations字段指向指针数组。将双向链表从named首节点处断开。

如果存在regex首节点,就分配r+1的指针数组,并依次将regex类型的location的指针(在链节点的exact字段)存储到指针数组中,数组的最后一个元素置为空指针,server层的父locationregex_locations字段指向指针数组。将双向链表从regex首节点处断开。

ngx_http_init_static_location_trees()对双向链表剩下的节点构建成三叉排序树,server层的父locationstatic_locations字段指向树的根节点。

经过调整后,读取配置指令时所建立的双向链结构就改变成了上述的结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值