nginx配置过程描述

  • 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; /* 配置项(指令)名字 */
    ngx_uint_t type; /* 配置项(指令)的类型block、main、server、app(location) 、args1、more1,类型含义参考深入理解nginx中的介绍*/
    char (*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); / 设置解析出的配置项(指令)参数到ctx中的方法 */
    ngx_uint_t conf; /* 配置项(指令)在module ctx中的offset,main offset、server offset、app(location) offset */
    ngx_uint_t offset; /* 配置项(指令)成员在的具体保存结构中的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)。

    • case 1:main对server层的管理,core main中有servers字段保存下层的配置结构
    • case 2:server对app层的管理,core server中有applications字段保存下层的配置结构
    • case 3:app,因为nginx的基础配置结构ngx_rtmp_conf_ctx_t中就3大层,到了app层次,其实有可能有很多子层次。
    • 拿rtmp来说,比如录制可以是一个配置块,比如live可以是一个配置块等等。rtmp是这样组织管理的:
    • 把所有的app的子配置块的配置都放到app块下产生的对应的rtmp core module的配置之中。
    • 拿录制来说,就会把所有的app下的录制子块的配置放到解析app配置块时产生的app_conf的第record module.ctx_index个录制配置(ngx_rtmp_record_app_conf_t)的rec数组中。
  • 解析流程

    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循环。
      之后校验参数,获取存储指令配置的存储上下文。cf的ctx是当前存储解析出来的配置的上下文,ngx_inti_cycle初始化为全局的配置根conf_ctx,其他时候各个解析的block自行赋值为当前block创建的存储配置的ctx。
      之后调用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字段的值,即直接存储该命令的数据结构的起始地址。

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

猜你喜欢

转载自blog.csdn.net/maxlovezyy/article/details/80283005