本篇的上篇 Nginx 源码分析:从模块到配置(上),建议阅读本篇前先阅读上篇。
关于模块
Nginx
的架构高度模块化。每个模块各司其职,组合在一起完成特定的功能。
Nginx
通过configure
决定哪些模块被安装。所有安装的模块在编译阶段静态生成,其指针被统一放入ngx_modules
数组中,供全局使用。
每个模块由以下几部分构成:
-
ngx_module_t
结构体:代表模块本身,其指针被放入ngx_modules
数组中。 -
ngx_<module name>_conf_t
结构体:用来表示模块的配置内容,其中部分成员可以通过配置文件进行配置。 -
ngx_<module name>_module_t
结构体:模块上下文,保存了一组操作,Nginx
初始化阶段调用这些操作,初始化ngx_<module name>_conf_t
中的成员。 -
ngx_command_t
结构体数组:该数组中每一项ngx_command_t
对应配置文件中一条指令。
Nginx
的模块虽然有很多。但是基本类型只有5种:CORF、CONF、EVNT、HTTP、MAIL
#define NGX_CORE_MODULE 0x45524F43 /* "CORE" */
#define NGX_CONF_MODULE 0x464E4F43 /* "CONF" */
#define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */
#define NGX_HTTP_MODULE 0x50545448 /* "HTTP" */
#define NGX_MAIL_MODULE 0x4C49414D /* "MAIL" */
每种类型对应一种ngx_<module name>_module_t
上下文结构体。Nginx
在初始化(主要在ngx_init_cycle
函数中)时根据不同的模块类型,调用不同的上下文中的操作,完成其配置内容的初始化。
虽然模块类型只有5种,但是模块数量可以有很多,每个模块都针对自身有特定的配置内容,这些配置内容中,可以被放到配置文件nginx.conf
中的,被包装成了一条条ngx_command_t
指令。这些指令的内容决定了nginx.conf
中可以写入的操作指令。
Nginx
初始化时解析nginx.conf
配置文件,找到对应的ngx_command_t
。调用该ngx_command_t
中的函数,该函数最终初始化模块对应的ngx_<module name>_conf_t
结构体,完成配置。
这就是模块和配置之间的关系。
配置文件、指令
谈到Nginx
的配置,首先想到的肯定是配置文件nginx.conf
。
众所周知,nginx.conf
配置文件的结构由一条条Nginx
配置指令构成(官方文档)。Nginx
配置指令可以分为两种:简单指令和块指令。
例如:
-
worker_processes 1;
就是一条简单指令 -
events { ... }
就是一条块指令
如果,一个块指令中含有其他指令,那么称这个块指令为上下文(注意区别模块中的上下文概念)。
例如:
events {
use epoll;
worker_connections 1024;
}
events
是块指令,由于events
中包含有指令(简单指令或块指令)。因此称events
为events上下文。
常见的上下文还有:http上下文、server上下文、location上下文。整个nginx.conf
文件称为main上下文
源码中的配置指令
前面提到过:Nginx
配置文件中的一条指令对应一个ngx_command_t
结构体。因此,分析源码中的配置指令,就是分析ngx_command_t
结构体。
ngx_command_t
结构体定义:
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
各成员含义如下:
name
:本条指令的名字,例如worker_processes 1;
对应的ngx_command_s.name
就是worker_processes
。
set
:函数指针,所以set
用来表示,当Nginx
解析配置文件,碰到指令时,该执行怎样的操作。而该操作本身,自然是用来设置本模块所对应的ngx_<module name>_conf_t
结构体。
conf
:这个变量只在NGX_HTTP_MODULE
类型的模块的ngx_command_t
使用。这个变量和今天讨论的话题关系不大。暂不讨论。
offset
:这个变量用来标记ngx_<module name>_conf_t
中某成员变量的偏移量,纯粹是为使用方便。
type
:配置指令属性的集合。例如,worker_processes
这条指令对应的type
定义为:
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1
其中,各个宏定义如下:
#define NGX_MAIN_CONF 0x01000000
#define NGX_DIRECT_CONF 0x00010000
#define NGX_CONF_TAKE1 0x00000002
-
NGX_MAIN_CONF
是指,该指令用于main上下文。 -
NGX_DIRECT_CONF
是指,该指令是用于main上下文的简单指令。 -
NGX_CONF_TAKE1
是指,该指令后跟一个参数,例如worker_processes 1;
的1
就是指后面跟一个参数,这个参数的数目由NGX_CONF_TAKE1
指定。
类似用来定义指令类型的宏还有很多,具体可以参考源码中各个模块中ngx_command_t
的设置。
几个典型的配置指令
daemon指令
Nginx
默认是以后台的形式运行的,这种运行形式被称为daemon
,当然,在调试的时候,为了方便,一般是关掉daemon
这种运行形式。
在配置文件中通过daemon
指令来打开或关闭。官方文档对daemon
指令说明如下:
Syntax: daemon on | off;
Default: daemon on;
Context: main
在源码中(core\nginx.c
),daemon
指令对应的ngx_command_t
结构体如下:
{ngx_string("daemon"), // 指令的名字daemon
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, // 指令的类型
ngx_conf_set_flag_slot, // 指令对应的操作
0,
offsetof(ngx_core_conf_t, daemon),
NULL }
其中,NGX_MAIN_CONF
指,daemon
指令的上下文为main上下文。NGX_DIRECT_CONF
指,daemon
指令是一条可以直接写在main上下文的简单指令。NGX_CONF_FLAG
指,daemon
指令是一个开关指令,接收on | off
作为指令参数。
user指令
Nginx
可以在配置文件中通过user
指令指定运行时所在的用户及用户组。官方文档对user
指令的说明如下:
Syntax: user user [group];
Default: user nobody nobody;
Context: main
在源码中(core\nginx.c
),user
对应的ngx_command_t
结构体定义如下:
{ ngx_string("user"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
ngx_set_user,
0,
0,
NULL },
其中NGX_MAIN_CONF
及NGX_DIRECT_CONF
的含义与daemon
指令的含义相同。NGX_CONF_TAKE12
是指该指令接收1个或两个参数,即Syntax: user user [group];
events指令
Nginx
中可以指定采用的事件监听机制类型,比如select、poll、epoll
等。
这个指定操作在events
指令中完成。这里events
指令为块指令。
官方文档对events
指令的定义如下:
Syntax: events { ... }
Default: —
Context: main
在源码中(event\ngx_event.c
),events
指令对应的ngx_command_t
结构体定义如下:
{ ngx_string("events"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_events_block,
0,
0,
NULL }
其中,NGX_MAIN_CONF
的含义与daemon
指令相同。NGX_CONF_BLOCK
是指,这是一条块指令。NGX_CONF_NOARGS
是指,该指令不接受参数。
总结
以上三条指令能够很清楚的说明,在Nginx
源码中是如何组织和管理配置文件中使用的配置指令的。
对于其他指令,可以直接阅读源码中该指令的定义。源码就是最好的文档。
关于模块和配置的总结
由于Nginx
是高度模块化的,因而,对Nginx
的配置一定是对模块的配置。
Nginx
的每条配置指令对应某模块中的一条ngx_command_t
定义。
每条ngx_command_t
一定操作了其所在模块的ngx_<module name>_conf_t
结构体中某些项。
Nginx
初始化时,首先解析配置文件,然后执行对应指令的ngx_command_t
中的操作函数,设置ngx_<module name>_conf_t
中的某些项,完成配置工作。
然后,Nginx
根据这些配置,执行启动流程,进而开始工作。
到此为止。本篇结束。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。