Nginx 配置文件解析

cycle = ngx_init_cycle(&init_cycle):

1、在内存池中分配一个ngx_cycle_t变量,并初始化它的各个成员。

2、调用core类型的create_conf,实际只有一个ngx_core_module_create_conf函数----初始化ngx_core_conf_t结构(存放core_module支持的指令),保存在ngx_cycle->conf_ctx数组中。可以说,此时,ngx_cycle->conf_ctx数组中只有一个ngx_core_conf_t结构。

3、初始化ngx_conf_t结构。

4、ngx_conf_parse 解析配置文件,把结果保存在模块对应的ngx_conf里面。

5、调用core类型的init_conf,实际只有一个ngx_core_module_init_conf函数(初始化对应的ngx_core_conf_t函数)。为什么要init,都已经解析配置文件了,应该在这之前初始化呀--如果值为-1,表明没有设置,初始化默认值!

6、ngx_open_listening_sockets:遍历listening数组并打开所有侦听sockets(socket()->setsockopt()->bind()->listen())。

7、调用所有模块的init_module(实际上只有ngx_event_core_module模块定义了该callback,即只有ngx_event_module_init()被调用)。

ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename):

函数的作用就是循环不停的从配置文件中读取指令,然后进行指令处理,直到结束

1、先分析ngx_core_module的指令及其对应的set函数。

{ ngx_string("daemon"),

NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,

ngx_conf_set_flag_slot,

0,

offsetof(ngx_core_conf_t, daemon),

//计算daemon成员在ngx_core_conf_t结构体里面的偏移

NULL },

ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf):里面代码很清楚,根据配置指令,设置模块conf结构的成员变量。

2、分析ngx_events_modules的指令及其对应的set函数。只有一条指令:

{ ngx_string("events"),

NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,

ngx_events_block,

0,

0,

NULL },

1、ngx_events_module编号为3,于是ngx_cycle->conf_ctx指向的void*数组第3号槽位指向一个void*指针,这个指针又指向一个void*数组(个数==事件类型模块的个数,Linux平台编译之后,只有两个ngx_epoll_module事件模型ngx_event_core_module和ngx_epoll_module)。

2、调用event类型模块的上下文ngx_event_module_t 的create_conf钩子,为void*数组指定槽位创建相应的conf结构。

3、更改当前cf环境(NGX_EVENT_MODULE,NGX_EVENT_CONF)解析events{ 块里面的指令。里面的set函数都是根据配置文件设置ngx_event_conf_t结构体里面的成员变量。

3、分析ngx_http_module的指令及其对应的set函数。只有一条指令,如下:

{ ngx_string("http"),

NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,

ngx_http_block,

0,

0,

NULL },

ngx_init_cycle创建了core module的config,那么http module相关的config在那里创建呢?http module相关的config是在ngx_http_block中创建(ngx_http_conf_ctx_t)的,在ngx_http_block中会创建,初始化,合并config(未完全看懂),以及整个http handler phase的初始化(还未看)等等。

1、为ngx_cycle->conf_ctx指向的void*数组创建ngx_http_conf_ctx_t结构,并为ngx_http_conf_ctx_t 创建main_conf srv_conf loc_conf三个void*数组,数组大小为http类型模块的个数。
2、遍历所有的http类型的模块的上下文ngx_http_module_t,调用create_main_conf、create_srv_conf、create_loc_conf 分别在ngx_http_conf_ctx_t 的三个数组(main_conf srv_conf loc_conf)的对应槽位创建响应的结构体变量。
3、遍历所有的http类型的模块的上下文ngx_http_module_t, 调用 preconfiguration 钩子函数。
4、解析http块里面的指令:ngx_conf_parse 未看,当前环境:ctx指向ngx_http_conf_ctx_t,指令类型为NGX_HTTP_MAIN_CONF,模块类型为:NGX_HTTP_MODULE。
4.1、 遇到http里面的main指令:
if (cmd->type & NGX_DIRECT_CONF) {
conf = ((void **) cf->ctx)[ngx_modules[i]->index]; //ngx_core_conf_t
} else if (cmd->type & NGX_MAIN_CONF) {
//hp: 比如,遇到http/events指令,这里,conf指向的是cf->ctx的第idx个槽位
conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
} else if (cf->ctx) {
//否则进入二级模块处理,比如events/http {里面的指令,都是在这里

//http 里面的main指令,ctx指向于ngx_http_conf_ctx_t
confp = *(void **) ((char *) cf->ctx + cmd->conf); //这里,cmd->conf的作用体现出来了
if (confp) {
//http里面的main指令: conf指向的是对应的ngx_http_core_main_conf_t
conf = confp[ngx_modules[i]->ctx_index];
}
}
比如variables_hash_max_size 指令:
{ ngx_string("variables_hash_max_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot, //这里,刚好设置conf(ngx_http_core_main_conf_t) 的variables_hash_max_size的值。
NGX_HTTP_MAIN_CONF_OFFSET, //这里,conf+NGX_HTTP_MAIN_CONF_OFFSET就是需要设置的结构体==ngx_http_core_main_conf_t变量地址
offsetof(ngx_http_core_main_conf_t, variables_hash_max_size), //需要设置结构体中的哪个成员,成员在结构体中的偏移。
NULL },
总结出struct ngx_command_s { // 这个域主要是供nginx解析配置文件时使用,设置相关的数据结构
ngx_str_t name;
//命令名称
ngx_uint_t type;
//命令类型(有几个参数等)
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); //这个conf指向需要设置的结构体变量地址
ngx_uint_t conf;
//配置结构体在内存的位置,相对于conf的偏移量,在ngx_conf_handler中使用
ngx_uint_t offset;
//要设置结构体的哪个成员,相对于结构体的偏移量
void *post;

//一些读取配置时候的零碎变量,一般为null

};

4.2 遇到 server指令时:

生成一个新的ngx_http_conf_ctx_t,其中main_conf指向原来的,server_conf和loc_conf创建新的void*数组。把ngx_http_core_module的server块配置信息存入 main_conf 中的server 容器里面。更新当前环境。 开始解析server块里面的指令。

cf->ctx = ctx; //指向新的ngx_http_conf_ctx_t

cf->cmd_type = NGX_HTTP_SRV_CONF;

4.3 遇到server里面的指令:遇到listen 指令时,ngx_conf_handler中,confp指向的新的ngx_http_conf_ctx_t.srv_conf所指向的void*数组,于是 conf = confp[ngx_modules[i]->ctx_index];指向listen指令对应的模块(ngx_htt_core_module)的 ngx_http_core_srv_conf_t数据结构。

4.4 遇到location指令:生成一个新的ngx_http_conf_ctx_t,其中main_conf指向原来的,srv_conf指向上一层ngx_http_conf_ctx_t的srv_conf数组,loc_conf创建新的void*数组。

ngx_http_core_location 这个函数很麻烦,看起来主要是设置ngx_http_loc_conf_ctx_t里面的name变量。然后递归调用ngx_parse_conf解析location里面的命令。

4.5: 遇到location里面的命令。比如 root,设置ngx_http_loc_conf_ctx_t里面的root变量。

5、回到ngx_http_block函数!遍历每个http类型的模块,调用模块上下文ngx_http_module_t中的init_main_conf钩子初始化模块对应的main_conf配置信息,然后调用ngx_http_merge_servers。

(0)

相关推荐

  • Nginx配置文件的详细说明

    #运行用户 user www-data; #启动进程,通常设置成和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 error_log /var/log/nginx ...

  • nginx配置文件vim语法高亮与缩进

    语法高亮设置 linux系统下vim或者vi编辑器默认是没有对nginx的语法高亮设置。 需要自己手动配置。 1.下载vi语法高亮配置到 ~/.vim/syntax,如果不存在则创建该目录 代码如下 ...

  • nginx 0.8.54/1.0.0 在cygwin环境下的编译(包括 nginx_mod_h264_streaming-2.2.7)

    一、概述: 由于测试需要在WIN平台上进行.264的MP4文件的拖动功能,而nginx windows官方版本不包含nginx_mod_h264_streaming-2.2.7模块,所以才有了本文。 ...

  • Nginx的error_log和Access_log分析

    nginx配置中有关日志的配置主要是围绕着下面两个指令: 1、error_log 2、access_log:记录访问日志 首先要强调的一点是,如果access日志和error日志都是常量文件名(因为a ...

  • linux系统中配置Nginx 拒绝代理访问指定IP的方法

    先大概说说简单的结构…前端一个Nginx反向代理,后端一个Nginx instance app for PHP…实际上就是个Discuz,之前面对CC攻击都是预警脚本或者走CDN,但是这次攻击者不再打 ...

  • Nginx安装配置PageSpeed模块实现网站加速

    作为Nginx组件,ngx_pagespeed将重写你的网页,让用户以更快的速度进行访问。重写的工作包括压缩图片、缩减CSS和JavaScript、扩展缓存时间,同样还包括其它一些最佳实践: 优化缓存 ...

  • Nginx负载均衡实战

    Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。与旧版本(<=2.2)的Apache不同,nginx不采用每客户机一线程的设计模 ...

  • 隐藏Nginx版本号的安全性与方法

    Nginx默认是显示版本号的,如: [root@bkjz ~]# curl -I www.45it.com HTTP/1.1 200 OK Server: nginx/0.8.44 Date: Tue ...

  • linux中配置Nginx 拒绝代理访问

    先大概说说简单的结构…前端一个Nginx反向代理,后端一个Nginx instance app for PHP…实际上就是个Discuz,之前面对CC攻击都是预警脚本或者走CDN,但是这次攻击者不再打 ...