nginx配置系统

来源:互联网 发布:首页源码 编辑:程序博客网 时间:2024/05/01 16:18

特此声明:转载需要说明且附上本人链接!

简述

 nginx是复杂的,因为它的设计高度抽象;nginx是简单的,因为它的设计高度抽象。我们学习一个系统,我认为最好是先了解其结构,这样才能带着关系去学习,之后通过流程深入理解。那么我就把我学习到的nginx的rtmp模块的配置系统的结构和加载流程记录下来,方便自己回顾以及新手学习。

内存布局

这里写图片描述
内存布局原图

- ngx模块的类型

 ngx有两种模块类型,一个ngx框架定义的核心级别的core module,一个是系列模块内的级别的模块类型。只有ngx的core module才会被ngx_core_module(nginx.c中的全局的core module)管理,ngx的core module同时也是系列module的配置解析初始控制模块,管理着系列module的根配置ctx的初始化。ngx的core module存储配置的ctx在ngx_cycle_t的conf_ctx之中,conf_ctx本身是一个指针,它里面存着各个ngx的core module的ctx指针,而各ngx的core module的ctx的结构里一般都有几个保存着各个层次,各个子module配置的指针数组,所以conf_ctx就成了一个四级指针。一个实现create_conf的module在create_conf时产生的ctx会存储在conf_ctx之中,或者在其模块名配置项(比如rtmp、http)解析的时候(ngx_rtmp_block、ngx_http_block函数)创建的ctx会存储在conf_ctx之中。

- ngx配置项(指令)

 放在配置文件里叫配置项,放到代码中叫指令(cmd)。

 配置项(指令)的结构:

struct ngx_command_s {  /* 配置项(指令)名字 */  ngx_str_t            name;   /* 配置项(指令)的类型block、main、server、app、args1、more1,类型含义参考深入理解nginx中的介绍*/  ngx_uint_t          type;      /* 设置解析出的配置项(指令)参数到ctx中的方法 */  char             *(*set)(ngx_conf_t *cf,       ngx_command_t *cmd, void *conf);  /* 配置项(指令)在module ctx中的offset,main offset、server offset、app offset */  ngx_uint_t          conf;   /* 配置项(指令)成员在的具体保存结构中的offset */  ngx_uint_t          offset;   /* 没仔细看,一般用不到。 */  void               *post;};

- 内存结构

 配置解析总的有个结构来存储吧?ngx的配置系统纵向是有层次的,但同时横向又区分module的,那你怎么来组织这些不同层次、不同module的配置?

 ngx的习惯是横向的系列的module的系列core module也就是系列的第一个module是系列的核心模块,比如ngx_rtmp_core_module,管理着纵向的子配置块生成的配置结构,一般核心main、server、app的配置都由这个模块掌控。

 拿rtmp模块来说,配置系统的基本结构(ngx_rtmp_conf_ctx_t, ngx_rtmp_module – ngx的core module)定义了三层,即main、server、app(http的话就是loc)。

  • main对server层的管理,core main中有servers字段保存下层的配置结构
  • server对app层的管理,core server中有applications字段保存下层的配置结构
  • app,因为nginx的基础配置结构ngx_rtmp_conf_ctx_t中就3大层,到了app层次,其实有可能有很多子层次。拿rtmp来说,比如录制可以是一个配置块,比如live可以是一个配置块等等。

加载流程

这里写图片描述
 加载流程原图

1> nginx启动的时候,nginx.c::main根据传入参数初始化一个 old_cycle中的几个属性,包括重要 的配置文件的路径。之后调用ngx_init_cycle函数并传入old_cycle开始配置的加载(当然包括其他动作,这里忽略)。
2> ngx_init_cycle调用ngx_conf_parse开始配置的解析,处理。
3> ngx_conf_parse先根据入参filename判断是否是最开始对文件的处理,如果是最开始对文件的处理,则初始化文件。之后进入循环开始解析处理。
 3.1> 调用ngx_conf_read_token读取一个指令(如果指令是NGX_OK, 说明遇到了”;”,这时候其实已经把cmd以及cmd的参数读取到cf->args中了),根据指令进行下一步处理。
 3.2> 如果指令为NGX_OK || NGX_CONF_BLOCK_START,则继续处理,否则结束ngx_conf_parse返回。
 3.3> 调用ngx_conf_handler函数进行具体的处理。
 3.4> ngx_conf_handler函数遍历每一个module
  3.4.1> 遍历这个module的每一个cmd。
   cf的module_type代表当前解析的块的类型,ngx_inti_cycle初始化赋值为NGX_CORE_MODULE,其他时候各个core module会根据当前情况赋值为当前的类型的core module值(某系列下的module的type都是一个值,那就是系列的module类型),如果当前module的类型不是cf正在解析的module的类型就会continue,否则继续。
   cf的cmd_type带包当前解析的块内的cmd类型,ngx_inti_cycle初始化赋值为NGX_MAIN_CONF,其他时候各个解析的block自行赋值为其类型(随便看一个block的命令解析函数就知道了),如果类型没问题,则继续,否则continue循环。

  3.4.2> 之后校验参数,获取存储指令配置的存储上下文。cf的ctx是当前存储解析出来的配置的上下文,ngx_inti_cycle初始化为全局的配置根conf_ctx,其他时候各个解析的block自行赋值为当前block创建的存储配置的ctx。

  3.4.3> 之后调用cmd的set函数指针开始cmd的赋值。cmd的set调用的*conf参数的取值为:

  • 如果cmd类型为NGX_DIRECT_CONF,则其值为ngx_init_cycle时cycle中初始化的conf_ctx中的对应core module的create_conf创建的配置,解析时就可以直接使用。
  • 如果cmd类型为NGX_MAIN_CONF,则其值为ngx_init_cycle时cycle中初始化的conf_ctx中的对应core module的位置的void指针的地址,需要在解析的现场初始化。
  • 如果cmd类型为其他,则其值为对应当前的block配置块下创建的ctx的offset为cmd的conf字段的值,即直接存储该命令的数据结构的起始地址。

如此递归下去,就完成了整个配置文件的所有命令的解析。

1 1
原创粉丝点击