本篇的上篇 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
的设置。
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
作为指令参数。
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];
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
根据这些配置,执行启动流程,进而开始工作。
到此为止。本篇结束。