浏览 901
概述
这几篇博客文章我们将会重点分析nginx配置项解析的原理。因为nginx配置框架设计的非常灵活和强大,这就使得我们在分析其内部机制的时候带来了不小的挑战,而这个系列的博客的意义就在于梳理其内部实现,并整理出大致框架,以分享给读者。
作者之前看过网上的一些博客写的关于nginx配置框架的梳理,粗制滥造,因此萌生了自己写的想法。希望大家能提出宝贵意见。
在讲配置之前,我们不得不简单说下nginx模块的概念。因为nginx属于微内核设计,nginx的强大之处在于灵活的微内核再加上可扩展的模块,nginx自身的模块有core、event、http、mail等核心模块,但是开发者又可以基于这些核心模块开发满足自身业务需求的模块,首当其冲的便是http模块了,因此,大家在阅读nginx代码的时候可以看到很多的ngx_http_xxx,这些都是基于http模块开发的第三方模块,而我们后面局里的重点也将会是http,谁叫他这么重要呢。
好了,言归正传,我们来看看nginx如何管理复杂的配置项吧。我在这里假设各位看官对nginx配置项的形式有了初步的了解,如果还没有配置过nginx的,那么请先移步,自行脑补再回头。
我们在本篇博客中会详细描述nginx配置解析的源头,从头干起,可避免在后面解析的时候的突兀感。
nginx的配置项的老祖宗就藏在下面这个数据结构了
当时看到这个结构的时候,我承认我有种淡淡的忧伤,我自认c语言也还不错,但是还是花了点时间才整明白这个四重指针到底是怎么指来指去的。而这个也是我们拨云见雾的第一步,我们可以并且必须搞清楚这鸟玩意到底是干嘛的。
首先看看它是如何诞生的:
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } ......}从这里我们看以看到,conf_ctx是一个指针数组,数组一共有ngx_max_module项(也就是nginx有多少个模块数组就有多大)。好了,除此之外,我们看不出更多信息。所以目前为止我们看到的结构如下:
那么接下来我们的任务就是弄清楚这个void*数组里面的每一项到底指向了谁
在这里,会调用每个模块的create_conf()方法,将结果保存在数组的对应项中。如core模块的ngx_core_module_create_conf(),然而对于大部分模块来说,其实并没有实现该方法,如我们关注的http_core模块,因此http_core模块对应的该项其实还是为NULL。此时数据结构图如下:
前面说过,对nginx的配置解析我们以http模块为例来说明,因此,接下来我们就来看看http模块的配置是如何一步步的被加载的。
在完成了配置数据结构的初始化以后,接下来就进入配置解析阶段了,我们不关心nginx是如何回调各模块的配置解析方法。我们就来看看nginx如何解析http配置。
首先,在nginx的配置设计中http模块的配置项位于下面的block
nginx遇到"http"指令时,会调用该指令的解析函数ngx_http_block
上面函数有一句非常重要
首先为http模块分配一个ngx_http_conf_ctx_t结构,然后再将该结构存储在conf指针指向的内存处,而追溯conf指针的来源是ngx_conf_handler():
由于"http"是http_core模块的指令,cmd->type满足NGX__MAIN_CONF,因此这里的conf其实就代表了cycle->conf_ctx[ngx_http_core_module]这项的地址,而
*(ngx_http_conf_ctx_t **) cof = ctx就是将ctx(指向ngx_http_conf_ctx结构的指针)放在数组的这一项里面,此时形成的结构如下图:
而接下来又会初始化该ngx_http_conf_ctx_t这个结构
形成的结构如下:
我想,话说到这个份上,大家应该能理解为什么cycle_conf_ctx是四重指针了吧。
按点赞数排序
按时间排序