文档章节

nginx源码分析——配置

hncscwc
 hncscwc
发布于 2016/06/13 23:21
字数 1472
阅读 254
收藏 11

1. 配置介绍

nginx的配置由一个主配置文件和其他一些辅助的配置文件构成。这些配置文件均是纯文本文件,这些配置文件全部位于nginx安装目录下的conf目录中。

主配置文件nginx.conf中的内容大概是这样子的:

#user nobody;
worker_processes    1;
pid                 logs/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    sendfile        on;
    keepalive_timeout 65;

    server {
        listen    80;
        server_name localhost;

        location / {
            root    html;
            index   index.html index.htm;
        }

        error_page    500 502 503 504 /50x.html;
        location = /50x.html {
            root    html;
        }
    }
}

从上面可以看出:nginx.conf由若干配置项组成,配置项又分为简单配置项和块配置项。

简单配置项由配置项名和配置项值构成。

配置项名是一个字符串,可以用单引号或者双引号括起来,也可以不扩。但是如果配置项名包含空格,则一定要括起来。配置项值使用一个或者多个空格或者TAB与配置项名分开,配置项值可以是数字或者字符串(当然也包括正则表达式)。一个配置项可以有多个配置项值,多个配置项值之间也由空格或者TAB分隔。简单配置项的结尾使用分号结束,其基本的语法格式如下:

配置项名    配置项值1  配置项值2 ... ;

块配置项由一个配置项名和一对大括号组成,其结尾不需要再添加分号。块配置项使用大括号把一系列所属的配置项全部包含起来,表示大括号内的配置项同时生效;块配置项也可以有配置项值,这取决于解析这个配置项的模块;块配置项可以嵌套,内层块直接继承外层块,同一个配置项可以同时出现在内外层块配置项中,其优先级也取决于解析该配置项的模块。

2. 配置解析流程

nginx配置解析的流程基本上是一个递归的过程,如下图所示:

在配置解析的入口函数 ngx_conf_parse 中会循环读取配置文件中的内容,每读取一行后就解析该配置项。解析的过程中可能会再次调用该函数完成后续配置项的解析,例如events块配置项,http块配置项的解析。

对应的源码:

char * ngx_conf_parse(ngx_conf_t * cf, ngx_str_t * filename)
{
    ...
    if( filename ){
        fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
        ...
    } else if(cf->conf_file->file.fd != NGX_INVALID_FILE){
        type = parse_block;
    } else {
        type = parse_param;
    }

    for( ;; ){
        rc = ngx_conf_read_token(cf);

        if(cf->handler){
            ...
        }

        rc = ngx_conf_handler(cf, rc);
    }
    ...
}

static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
    for(i = 0; cf->cycle->modules[i]; i++){
        cmd = cf->cycle->modules[i]->commands;
        if(cmd == NULL){
            continue;
        }

        for( ; cmd->name.len; cmd++ ){
            if( name->len != cmd->name.len){
                continue;
            }
            if(ngx_strcmp(name->data, cmd->name.data) != 0){
                continue;
            }
            found = 1;
            ...
            rc = cmd->set(cf, cmd, conf);
        }
    }
}

ngx_conf_parse函数支持三种不同的解析环境:

  • parse_file:解析配置文件
  • parse_block: 解析块配置项
  • parse_param:解析命令行配置。(注:命令行配置不支持块配置项)

从前面的解析流程可以看出,首次调用ngx_conf_parse进行配置解析时,类型为parse_file,当递归调用时,ngx_conf_parse的filename参数均设置为空,即正在进行块配置项的解析,例如:

static char * ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ...
    cf->ctx = ctx;
    cf->module_type = NGX_EVENT_MODULE;
    cf->cmd_type = NGX_EVENT_CONF;

    rv = ngx_conf_parse(cf, NULL);
    ...
}


在ngx_conf_handler的校验过程中会针对模块类型、配置项类型、配置项值个数等进行校验。

  • 模块类型:校验配置项所属的模块是否为当前处理配置项解析的模块。
if( cf->cycle->modules[i]->type != NGX_CONF_MODULE && 
    cf->cycle->modules[i]->type != cf->module_type ){
    continue;
}

    cf->module_type 初始值设置为 NGX_CORE_MODULE(在ngx_init_cycle函数中初始化),解析到配置项 http { 的时候,找到ngx_http_module模块,并调用ngx_http_block处理该配置项。从ngx_http_module模块的定义可以看到其类型确实为NGX_CORE_MODULE。

static ngx_command_t ngx_http_commands[] = {
    { ngx_string("http"),
      NGX_MAIN_CONF | NGX_CONF_BLOCK | NGX_CONF_NOARGS,
      ngx_http_block,
      0,
      0,
      NULL
    },
    ngx_null_command
};

ngx_module_t ngx_http_module = {
    NGX_MODULE_V1,
    &ngx_http_module_ctx,
    ngx_http_commands,
    NGX_CORE_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_P1_PADDING
};

在ngx_http_block中将cf->module_type设置为NGX_HTTP_MODULE,解析http块配置项中的其他配置项时,找到对应的http模块并进行后续处理,而所有http模块的类型均定义为NGX_HTTP_MODULE。 这样,可有效防止配置项被其他模块所处理。

  • 配置项类型:与模块类型类似
if(!(cmd->type & cf->cmd_type)){
    continue;
}

    cmd->type初始值为NGX_MAIN_CONF,前面提到的ngx_http_module模块的配置项数组中http配置项的类型包含了NGX_MAIN_CONF。

  • 配置项值的个数

    前面提到每个配置项名后可以有多个配置项值,当前配置项值的最大个数定义为8。代码中有相关的宏对应。配置项值的个数必须正确才能进行实际的配置项解析。

#define  NGX_CONF_MAX_ARGS  8
#define  NGX_CONF_NOARGS    0x00000001  //无配置项值
#define  NGX_CONF_TAKE1     0x00000002  //接受1个配置项值
#define  NGX_CONF_TAKE2     0x00000004  //接受2个配置项值
#define  NGX_CONF_TAKE3     0x00000008  //接受3个配置项值
#define  NGX_CONF_TAKE4     0x00000010  //接受4个配置项值
#define  NGX_CONF_TAKE5     0x00000020  //接受5个配置项值
#define  NGX_CONF_TAKE6     0x00000040  //接受6个配置项值
#define  NGX_CONF_TAKE7     0x00000080  //接受7个配置项值
#define  NGX_CONF_BLOCK     0x00000100  //接受块配置项
#define  NGX_CONF_FLAG      0x00000200  //接受配置项值为on或者off
#define  NGX_CONF_ANY       0x00000400  //接受任意的配置项值
#define  NGX_CONF_1MORE     0x00000800  //至少1个配置项值
#define  NGX_CONF_2MORE     0x00001000  //至少2个配置项值
#define  NGX_CONF_MULTI     0x00000000  //接受多个配置项值 个数不定

//接受1个或2个配置项值
#define NGX_CONF_TAKE12     (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
//接受1个或3个配置项值
#define NGX_CONF_TAKE13     (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
//接受2个或3个配置项值
#define NGX_CONF_TAKE23     (NGX_CONF_TAKE2|NGX_CONF_TAKE2)
//接受1个或2个或3个配置项值
#define NGX_CONF_TAKE123    (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3)
//接受1个或2个或4个配置项值
#define NGX_CONF_TAKE1234   (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3|NGX_CONF_TAKE4)

参考:

《深入理解nginx》

《nginx开发从入门到精通》

© 著作权归作者所有

hncscwc
粉丝 66
博文 70
码字总数 76137
作品 0
杭州
程序员
私信 提问
nginx源码分析—启动流程

作者:阿波 本文链接: http://blog.csdn.net/livelylittlefish/article/details/7243718 Content 0. 序 1. main()分析 2. 注意问题 2.1 几个初值 2.2 nginx工作模式 2.3 一些配置 2.4 其他开...

晨曦之光
2012/03/09
1K
0
nginx源码分析—hash结构ngx_hash_t(v1.0.4)

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(阿波)相关研究、学习内容所做的笔记,欢迎广大朋友指正! Content 0.序 1.hash结构 1.1ngx_hash_t结构 1.2ngx_hash_init_t结构...

晨曦之光
2012/03/09
757
0
nginx 源码调试

这段时间正在学习nginx源码,看到一贴子的提问 (帖子:http://www.oschina.net/question/27119912165566?p=1#AnchorAnswer1114315),决定试试能不能搞定。 这个帖子的主要问题是,自己写的...

悬崖
2016/04/14
264
1
nginx源码分析—队列结构ngx_queue_t

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(阿波)相关研究、学习内容所做的笔记,欢迎广大朋友指正! Content 0. 序 1. 队列结构 2. 队列操作 2.1 在头节点之后插入 2.2 ...

晨曦之光
2012/03/09
238
2
nginx源码分析—数组结构ngx_array_t

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(阿波)相关研究、学习内容所做的笔记,欢迎广大朋友指正! Content 0.序 1.数组结构 1.1ngx_array_t结构 1.2ngx_array_t的逻辑结...

晨曦之光
2012/03/09
205
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
2.4K
15
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
41
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
21
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部