4.5.1 Nginx反向代理与系统参数配置
1、nginx使用conf配置
2、nginx模块开发 hander ,filter,upstream
3、nginx源码 多线程网络,http状态机,多进程网络加锁
4、nginx基础组件、线程池、内存池、原子、共享内存,string,list,hash,array
二、步骤
5、解压四个文件
6、配置文件
yang@ubuntu:~/sambashare/4.5.1nginx/Nginx/nginx-1.22.1 ./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_addition_module --with-http_ssl_module --with-http_gzip_static_module --with-http_secure_link_module --with-http_stub_status_module --with-stream --with-pcre=/home/yang/sambashare/4.5.1nginx/Nginx/pcre-8.45 --with-zlib=/home/yang/sambashare/4.5.1nginx/Nginx/zlib-1.2.13 --with-openssl=/home/yang/sambashare/4.5.1nginx/Nginx/openssl-1.1.1s
7、make
8、sudo make install
9、yang@ubuntu:~/sambashare/4.5.1nginx/Nginx/nginx-1.22.1$ cd /usr/local/nginx/
10、yang@ubuntu:/usr/local/nginx$ sudo ./sbin/nginx -c conf/nginx.conf 运行
11、yang@ubuntu:/usr/local/nginx$ sudo ./sbin/nginx -reload conf/nginx.conf
12、yang@ubuntu:/usr/local/nginx$ sudo ./sbin/nginx -s conf/nginx.conf
king.conf
./sbin/nginx -? 如下所示
| 命令 | 作用 |
|---|---|
-h 或 -? |
显示帮助信息 |
-v |
显示 Nginx 版本号 |
-V |
显示版本号 + 编译参数(非常重要!可查看是否启用了某模块) |
-t |
测试配置文件语法是否正确(不启动服务) |
-T |
测试配置并打印所有加载的配置内容(调试神器) |
-c file |
指定配置文件路径(默认是 conf/nginx.conf)例: ./sbin/nginx -c /my/custom.conf |
-p prefix |
设置前缀路径(即 --prefix 的运行时覆盖)例: ./sbin/nginx -p /home/user/mynginx/ |
-g directives |
设置全局配置指令(临时覆盖) 例: ./sbin/nginx -g "worker_processes 2;" |
一、Nginx 配置文件片段,详细分析:
✅ 配置内容

🔍 逐行解析
1. worker_processes 4;
- 设置 Nginx 启动 4 个工作进程(worker process)。
- 每个进程独立运行,可以并行处理请求。
- 建议设置为 CPU 核心数(或略多),这里可能是 4 核 CPU。
✅ 推荐:
worker_processes auto;可自动识别核心数。
2. events { ... }
- 定义事件模型参数,影响并发性能。
worker_connections 1024;
- 每个工作进程最多可同时处理 1024 个连接。
- 总最大并发连接数 =
worker_processes × worker_connections
→ 这里是4 × 1024 = 4096个并发连接。
💡 注意:这只是一个上限,实际性能还受系统资源、网络、后端服务等影响。
3. http { ... }
- HTTP 模块配置块,包含所有虚拟主机(server)的定义。
4. 四个 server 块
每个 server 块监听一个不同的端口:
| 端口 | 作用 |
|---|---|
listen 8000; |
监听 8000 端口 |
listen 8001; |
监听 8001 端口 |
listen 8002; |
监听 8002 端口 |
listen 8003; |
监听 8003 端口 |
出现的问题
1、无法进入 /home/yang 目录 → 无法访问里面的文件 → 403 Forbidden
✅ 方案:给 /home/yang 添加 others 的执行权限(最快,适合测试环境)
1chmod o+x /home/yang
执行后权限变为
drwxr-x--x(751)或drwxr-xr-x(755)这样
others就能“进入”该目录(x权限),进而访问子目录中的文件(前提是子目录也开放权限)。
✅ 验证:
1ls -ld /home/yang
2# 应显示 drwxr-x--x 或 drwxr-xr-x
然后重载 Nginx(其实不用重载,权限改完立即生效):
1curl http://192.168.198.135:9003
4.5.2 Nginx过滤器模块实现
1、组件如何使用
2、过滤器模块实现
组件

代码编译/home/yang/sambashare/4.5.1nginx/zip/ngx_str代码
4.5.3
./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_addition_module --with-http_ssl_module --with-http_gzip_static_module --with-http_secure_link_module --with-http_stub_status_module --with-stream --with-pcre=/home/yang/sambashare/4.5.1nginx/Nginx/pcre-8.45 --with-zlib=/home/yang/sambashare/4.5.1nginx/Nginx/zlib-1.2.13 --with-openssl=/home/yang/sambashare/4.5.1nginx/Nginx/openssl-1.1.1s --add-module=/home/yang/sambashare/4.5.1nginx/ngx_code_test_/ngx_http_voice_filter_module
config文件


二、struct ngx_command_s 结构体
struct ngx_command_s 是 Nginx 配置系统的核心数据结构之一,用于描述一个配置指令(directive)的元信息。每一个 Nginx 模块若想在配置文件中提供可配置项(如 gzip on;、worker_processes 4;),就必须定义一个或多个 ngx_command_t(即 ngx_command_s 的 typedef)类型的结构体。
下面逐字段详细解释其含义和作用:
📌 结构体定义(带注释)
struct ngx_command_s {
ngx_str_t name; // 指令名称(如 "gzip", "listen")
ngx_uint_t type; // 指令类型标志(上下文、参数个数、是否为块等)
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
// 指令解析函数(核心!)
ngx_uint_t conf; // 指定该指令作用于哪类配置结构体(main/srv/loc)
ngx_uint_t offset; // 该指令值在配置结构体中的偏移量(字节)
void *post; // 后处理回调(可选,用于校验或触发逻辑)
};
💡 在 Nginx 源码中通常使用
typedef struct ngx_command_s ngx_command_t;,所以你常看到的是ngx_command_t。
🔍 字段详解
1. ngx_str_t name
- 作用:指令的名称字符串。
- 示例:
ngx_string("gzip"), // 对应配置:gzip on; ngx_string("worker_processes") - 注意:必须用
ngx_string()宏初始化,它会自动设置.len和.data。
2. ngx_uint_t type
- 作用:复合标志位,描述指令的使用规则,包括:
- 指令可用的上下文(main / http / server / location 等)
- 指令接受的参数个数
- 是否是块指令(如
http { ... }) - 指令的数据类型(flag、num、string、take1~7 等)
常见标志组合(按位或 |):
| 标志 | 含义 |
|---|---|
NGX_MAIN_CONF |
可在 main 上下文使用(如 worker_processes) |
NGX_HTTP_MAIN_CONF |
可在 http{} 块内使用 |
NGX_HTTP_SRV_CONF |
可在 server{} 块内使用 |
NGX_HTTP_LOC_CONF |
可在 location{} 块内使用 |
NGX_CONF_FLAG |
参数必须是 on 或 off |
NGX_CONF_TAKE1 |
必须且只能有 1 个参数(如 root /var/www;) |
NGX_CONF_TAKE2 |
必须有 2 个参数(如 proxy_pass http://backend;) |
NGX_CONF_NOARGS |
无参数(如 daemon off; 实际有参数,此例不恰当;更好的例子是某些开关) |
NGX_CONF_1MORE |
至少 1 个参数 |
NGX_CONF_2MORE |
至少 2 个参数 |
NGX_CONF_BLOCK |
是一个块指令(如 http, server) |
NGX_CONF_ANY |
任意参数个数 |
✅ 示例:
NGX_HTTP_LOC_CONF | NGX_CONF_FLAG
// 表示:该指令可在 location 块中使用,且值为 on/off
3. char *(*set)(...)
- 作用:指令解析回调函数,当 Nginx 解析到该指令时,会调用此函数。
- 函数签名:
char *set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);cf:当前配置上下文(含参数、日志、文件名行号等)cmd:指向当前ngx_command_t自身conf:指向当前上下文对应的配置结构体(如 location 配置)
- 返回值:
- 成功:返回
NULL(通常用NGX_CONF_OK表示) - 失败:返回错误信息字符串(如
"invalid value")或NGX_CONF_ERROR
- 成功:返回
常用内置 set 函数:
| 函数 | 用途 |
|---|---|
ngx_conf_set_flag_slot |
解析 on/off → 存入 ngx_flag_t 字段 |
ngx_conf_set_num_slot |
解析数字 → 存入 ngx_int_t |
ngx_conf_set_size_slot |
解析带单位的大小(如 1k, 2m) |
ngx_conf_set_str_slot |
解析字符串 → 存入 ngx_str_t |
ngx_http_upstream_server |
解析 upstream 中的 server 指令 |
✅ 开发者也可以自定义
set函数以实现复杂逻辑。
4. ngx_uint_t conf
- 作用:指定该指令影响哪一类配置结构体。
- 常用值:
值 含义 NGX_HTTP_MAIN_CONF_OFFSET主配置(http 块外) NGX_HTTP_SRV_CONF_OFFSETserver 块配置 NGX_HTTP_LOC_CONF_OFFSETlocation 块配置 NGX_HTTP_UPS_CONF_OFFSETupstream 块配置
💡 这个字段告诉 Nginx:当解析到该指令时,应该把值写入哪个层级的配置结构体中。
5. ngx_uint_t offset
- 作用:目标字段在配置结构体中的字节偏移量。
- 如何获取?使用 C 标准宏
offsetof:offsetof(ngx_http_my_loc_conf_t, enable_cache) - 为什么需要?
- Nginx 的
set函数是通用的(如ngx_conf_set_flag_slot)。 - 它通过
void *conf + offset的方式,动态定位到具体字段并写入值。 - 这是实现“一套解析函数,适配所有模块”的关键设计!
- Nginx 的
✅ 示例:
typedef struct {
ngx_flag_t gzip;
size_t buffer_size;
} my_conf_t;
// 指令定义:
{ ngx_string("gzip"), ..., offsetof(my_conf_t, gzip), ... }
→ set 函数就能把 on 写入 conf->gzip。
6. void *post
- 作用:后处理回调指针,通常指向
ngx_conf_post_t类型。 - 用途:
- 在值被写入后执行额外操作(如校验范围、触发初始化、设置全局变量)
- 例如:检查
worker_connections是否超过系统限制
使用方式:
static ngx_conf_post_t my_post = { ngx_my_post_handler };
static ngx_command_t cmds[] = {
{ ..., &my_post },
};
static char *
ngx_my_post_handler(ngx_conf_t *cf, void *data, void *conf)
{
ngx_flag_t *fp = conf;
if (*fp) {
// do something when enabled
}
return NGX_CONF_OK;
}
⚠️ 注意:不是所有指令都需要
post,很多简单指令设为NULL。
🧩 完整示例:定义一个 my_cache on|off; 指令
// 1. 配置结构体
typedef struct {
ngx_flag_t my_cache;
} ngx_http_my_loc_conf_t;
// 2. 后处理(可选)
static ngx_conf_post_t my_cache_post = { NULL }; // 这里省略
// 3. 指令定义
static ngx_command_t ngx_http_my_commands[] = {
{ ngx_string("my_cache"),
NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
ngx_conf_set_flag_slot, // 使用内置解析函数
NGX_HTTP_LOC_CONF_OFFSET, // 作用于 location 配置
offsetof(ngx_http_my_loc_conf_t, my_cache), // 写入 my_cache 字段
NULL }, // 无 post handler
ngx_null_command
};
配置文件中即可使用:
location / {
my_cache on;
}
✅ 总结:ngx_command_t 的设计哲学
| 特点 | 说明 |
|---|---|
| 声明式 | 模块只需“声明”指令规则,无需手动解析 |
| 通用性 | 通过 offset + set 机制,一套解析函数服务所有模块 |
| 类型安全 | type 字段在解析前就做上下文和参数校验 |
| 可扩展 | 支持自定义 set 和 post 实现任意逻辑 |
这个结构体是 Nginx 高度模块化、配置驱动架构的基石之一。
如果你正在开发 Nginx 模块,理解 ngx_command_t 是必经之路。
三、struct ngx_module_s结构体
struct ngx_module_s(通常通过 typedef 称为 ngx_module_t)是 Nginx 模块系统的核心结构体。每一个 Nginx 模块(无论是 HTTP 模块、事件模块、核心模块还是第三方模块)都必须定义一个类型为 ngx_module_t 的全局变量,用于向 Nginx 内核“注册”自身的能力、配置、生命周期回调等信息。
下面我们将逐字段详细解析其作用、设计意图和使用方式。
🧱 整体结构概览
struct ngx_module_s {
// 1. 元信息与 ABI 兼容性字段
ngx_uint_t ctx_index;
ngx_uint_t index;
char *name;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t version;
const char *signature;
// 2. 模块核心功能描述
void *ctx; // 模块上下文(类型由 module type 决定)
ngx_command_t *commands; // 配置指令列表
ngx_uint_t type; // 模块类型(NGX_HTTP_MODULE 等)
// 3. 生命周期回调函数(按启动/关闭顺序)
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
// 4. 预留扩展字段(用于未来兼容)
uintptr_t spare_hook0 ... spare_hook7;
};
🔍 一、元信息与 ABI 兼容性字段(前7个)
这些字段主要用于 模块识别、加载校验和内部索引管理,通常由宏 NGX_MODULE_V1 自动初始化。
1. ngx_uint_t ctx_index
- 作用:该模块在其同类模块中的索引。
- 示例:所有
NGX_HTTP_MODULE类型的模块会被放入一个数组,ctx_index表示它在该数组中的位置。 - 用途:用于快速定位模块上下文(如 HTTP 模块的
main_conf、srv_conf数组)。 - 初始化:设为
NGX_MODULE_UNSET_INDEX(即(ngx_uint_t)-1),由 Nginx 启动时自动分配。
2. ngx_uint_t index
- 作用:该模块在所有已加载模块中的全局唯一索引。
- 用途:用于通用模块遍历、日志标记等。
- 同样由 Nginx 自动分配。
3. char *name
- 作用:模块名称(字符串)。
- 实际使用:很少用到,通常设为
NULL。 - 调试时可能有用。
4–5. spare0, spare1
- 保留字段,必须初始化为
0。 - 用于未来扩展,保持结构体对齐或添加新字段而不破坏 ABI。
6. ngx_uint_t version
- 作用:Nginx 核心版本号(如
1022001表示 1.22.1)。 - 必须等于编译时的
nginx_version宏。 - 用途:防止加载用不同版本 Nginx 编译的模块(避免 ABI 不兼容导致崩溃)。
7. const char *signature
- 作用:模块签名字符串,包含:
- 操作系统类型(Linux/FreeBSD)
- 编译器(gcc/clang)
- 编译选项(是否启用
-O2、--with-debug等) - 内存对齐方式
- 指针大小等
- 生成方式:在
auto/configure阶段自动生成,定义在objs/ngx_auto_config.h中。 - 用途:严格校验模块是否与当前 Nginx 二进制完全兼容。
✅ 这7个字段通常用
NGX_MODULE_V1宏一键初始化。
🔧 二、模块核心功能描述(中间3个)
这是模块“能力”的核心声明。
8. void *ctx
- 作用:模块上下文指针,其真实类型由
type字段决定。 - 关键点:这是一个泛型指针,Nginx 根据模块类型进行强制转换。
常见类型对应关系:
type 值 |
ctx 实际类型 |
说明 |
|---|---|---|
NGX_HTTP_MODULE |
ngx_http_module_t* |
包含 create/init 回调,用于创建 main/srv/loc 配置 |
NGX_CORE_MODULE |
ngx_core_module_t* |
如 ngx_errlog_module |
NGX_EVENT_MODULE |
ngx_event_module_t* |
事件驱动模型(epoll/kqueue) |
NGX_MAIL_MODULE |
ngx_mail_module_t* |
邮件代理模块 |
✅ 示例(HTTP 模块):
static ngx_http_module_t ngx_http_my_ctx = {
NULL, /* preconfiguration */
ngx_http_my_init, /* postconfiguration */
NULL, /* create main conf */
NULL, /* init main conf */
NULL, /* create srv conf */
NULL, /* merge srv conf */
ngx_http_my_create_loc_conf, /* create loc conf */
ngx_http_my_merge_loc_conf /* merge loc conf */
};
ngx_module_t ngx_http_my_module = {
NGX_MODULE_V1,
&ngx_http_my_ctx, // ← ctx 指向 ngx_http_module_t
ngx_http_my_commands,
NGX_HTTP_MODULE,
// ... callbacks ...
};
9. ngx_command_t *commands
- 作用:指向该模块支持的配置指令数组(以
ngx_null_command结尾)。 - 用途:Nginx 解析配置文件时,根据指令名匹配到此数组中的条目,并调用其
set函数。 - 若无配置项,可设为
NULL。
10. ngx_uint_t type
- 作用:模块类型,决定 Nginx 如何处理该模块。
- 常用值:
#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' #define NGX_STREAM_MODULE 0x54414552 // 'REAT' (Stream) - 重要性:决定了:
ctx的解释方式- 模块在启动流程中的处理阶段
- 配置结构体的创建时机
⏳ 三、生命周期回调函数(7个函数指针)
Nginx 在不同阶段调用这些回调,实现模块的初始化和清理。
| 回调函数 | 调用时机 | 参数 | 返回值 | 典型用途 |
|---|---|---|---|---|
init_master |
Master 进程启动早期(仅一次) | ngx_log_t *log |
NGX_OK / NGX_ERROR |
初始化全局资源(如共享内存、信号) |
init_module |
所有模块加载完成后,fork 子进程前 | ngx_cycle_t *cycle |
NGX_OK / NGX_ERROR |
初始化模块级资源(如连接池、监听 socket) |
init_process |
每个 Worker 进程启动时 | ngx_cycle_t *cycle |
NGX_OK / NGX_ERROR |
初始化进程私有资源(如定时器、event loop) |
init_thread |
线程池启用时(极少用) | ngx_cycle_t *cycle |
NGX_OK / NGX_ERROR |
初始化线程局部数据 |
exit_thread |
线程退出时 | ngx_cycle_t *cycle |
void | 清理线程资源 |
exit_process |
Worker 进程退出时 | ngx_cycle_t *cycle |
void | 清理进程资源(如关闭 fd、释放内存) |
exit_master |
Master 进程退出时 | ngx_cycle_t *cycle |
void | 清理全局资源 |
💡 注意:
- 大多数模块只用
init_module和init_process。- 如果不需要某阶段回调,设为
NULL。init_process是最常用的,因为 Worker 进程在此时才真正开始工作。
🧩 四、预留扩展字段(8个 spare_hook)
uintptr_t spare_hook0 ... spare_hook7;
- 作用:为未来 Nginx 版本预留的回调或字段,保证结构体大小稳定。
- 当前必须初始化为 0(通常由
NGX_MODULE_V1_PADDING宏完成)。 - 设计哲学:避免因新增字段导致旧模块因结构体大小不匹配而崩溃。
✅ 使用
NGX_MODULE_V1_PADDING宏来填充这些字段。
✅ 完整模块定义示例(HTTP 模块骨架)
static ngx_http_module_t ngx_http_my_module_ctx = {
NULL, NULL, NULL, NULL, NULL, NULL,
ngx_http_my_create_loc_conf,
ngx_http_my_merge_loc_conf
};
static ngx_command_t ngx_http_my_commands[] = {
{ ngx_string("my_flag"),
NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_my_loc_conf_t, flag),
NULL },
ngx_null_command
};
ngx_module_t ngx_http_my_module = {
NGX_MODULE_V1,
&ngx_http_my_module_ctx, /* ctx */
ngx_http_my_commands, /* commands */
NGX_HTTP_MODULE, /* type */
NULL, /* init_master */
NULL, /* init_module */
NULL, /* init_process */
NULL, /* init_thread */
NULL, /* exit_thread */
NULL, /* exit_process */
NULL, /* exit_master */
NGX_MODULE_V1_PADDING
};
📌 总结:ngx_module_t 的设计思想
| 特点 | 说明 |
|---|---|
| 统一接口 | 所有模块通过同一结构体向内核注册 |
| 类型驱动 | type 决定 ctx 解释方式和处理流程 |
| 生命周期管理 | 提供完整的 init/exit 钩子 |
| ABI 安全 | 通过 version + signature 防止不兼容模块加载 |
| 可扩展性 | 预留字段 + 宏封装,支持未来演进 |
理解 ngx_module_t 是深入 Nginx 模块开发的基石。它体现了 Nginx 高度模块化、低耦合、高性能的架构哲学。
如果你正在编写 Nginx 模块,务必正确初始化这个结构体!
四、Nginx HTTP 模块系统
ngx_http_module_t 是 Nginx HTTP 模块系统中的核心结构体之一,用于定义一个 HTTP 模块在整个 Nginx 配置生命周期中各个阶段的行为。它本质上是一个回调函数表(callback table),通过函数指针将模块的配置逻辑“钩入”到 Nginx 的配置解析与初始化流程中。
下面我们将逐字段详细分析这个结构体的每一个成员,包括其作用、调用时机、参数含义、返回值规范以及典型使用场景。
结构体定义回顾
typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
一、配置前/后处理阶段
1. preconfiguration
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
- 作用:在 Nginx 开始解析 HTTP 配置块(即
http { ... })之前调用。 - 调用时机:仅在主配置阶段(main configuration phase)中,进入
http块解析前。 - 用途:
- 注册变量(如
ngx_http_add_variable) - 添加阶段处理器(phase handlers),但注意:通常在
postconfiguration中注册更安全 - 初始化一些全局资源(如共享内存、哈希表等)
- 注册变量(如
- 返回值:
NGX_OK:成功NGX_ERROR:失败,Nginx 启动终止
- 注意:此时所有配置结构体尚未创建,不能访问
srv_conf或loc_conf。
✅ 典型用法:注册自定义变量(如
$my_var)
2. postconfiguration
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
- 作用:在 整个 HTTP 配置解析完成之后 调用(即所有
server、location块都已解析完毕)。 - 调用时机:HTTP 配置解析结束、worker 进程启动前。
- 用途:
- 最关键的用途:向 HTTP 请求处理的 11 个阶段(phases)中插入自己的 handler(如
ngx_http_core_rewrite_phase、ngx_http_core_access_phase等) - 完成模块的最终初始化(如构建查找表、验证配置一致性等)
- 最关键的用途:向 HTTP 请求处理的 11 个阶段(phases)中插入自己的 handler(如
- 返回值:同上,
NGX_OK或NGX_ERROR - 重要性:绝大多数模块在此处注册 handler。
✅ 典型用法:
ngx_http_core_main_conf_t *cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.elts = ...;
二、Main 配置(http 块级别)
Nginx 的配置是分层的:main → server → location。每个层级都有独立的配置结构体。
3. create_main_conf
void *(*create_main_conf)(ngx_conf_t *cf);
- 作用:为当前模块在
http { ... }块中创建主配置结构体(main configuration context)。 - 调用时机:当 Nginx 解析到
http块时,为每个 HTTP 模块调用一次。 - 返回值:
- 成功:指向新分配的配置结构体(如
my_module_main_conf_t *) - 失败:返回
NULL(但通常应使用ngx_pcalloc并检查)
- 成功:指向新分配的配置结构体(如
- 典型实现:
static void * ngx_http_my_module_create_main_conf(ngx_conf_t *cf) { ngx_http_my_module_main_conf_t *mcf; mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_my_module_main_conf_t)); if (mcf == NULL) { return NULL; } // 初始化默认值,如 mcf->flag = NGX_CONF_UNSET; return mcf; }
⚠️ 注意:不要在这里做复杂逻辑,只负责分配和设默认值。
4. init_main_conf
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
- 作用:在
http块解析完成后,对主配置进行最终初始化或验证。 - 调用时机:在
http块解析结束、进入server块之前。 - 参数:
conf:即create_main_conf返回的指针
- 返回值:
- 成功:返回
NGX_CONF_OK(即(char *)NULL) - 失败:返回错误信息字符串(如
"my_module: missing required parameter")
- 成功:返回
- 用途:
- 检查必填项是否设置
- 将
NGX_CONF_UNSET替换为真实默认值 - 构建内部数据结构(如正则表达式编译)
✅ 示例:
if (mcf->size == NGX_CONF_UNSET_SIZE) { mcf->size = 1024; }
三、Server 配置(server 块级别)
5. create_srv_conf
void *(*create_srv_conf)(ngx_conf_t *cf);
- 作用:为每个
server { ... }块创建该模块的 server 级配置。 - 调用时机:每当遇到一个新的
server块时调用。 - 返回值:新分配的 server 配置结构体指针。
- 注意:不同
server块有各自独立的配置实例。
💡 提示:如果模块不关心
server级配置,可返回NULL,但通常仍需创建空结构以支持 merge。
6. merge_srv_conf
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
- 作用:将父级(通常是 main)配置合并到当前 server 配置中。
- 参数:
prev:上级配置(通常是 main conf)conf:当前 server 的配置
- 调用时机:在
server块解析完成后。 - 返回值:
- 成功:
NGX_CONF_OK - 失败:错误字符串
- 成功:
- 合并逻辑:
- 如果
conf中某字段未设置(如== NGX_CONF_UNSET),则从prev继承 - 若两者都未设置,则使用硬编码默认值
- 如果
- 重要性:实现配置继承机制的关键!
✅ 示例:
if (conf->timeout == NGX_CONF_UNSET_MSEC) { conf->timeout = prev->timeout; // 从 main 继承 } if (conf->timeout == NGX_CONF_UNSET_MSEC) { conf->timeout = 60000; // 默认 60s }
四、Location 配置(location 块级别)
7. create_loc_conf
void *(*create_loc_conf)(ngx_conf_t *cf);
- 作用:为每个
location /xxx { ... }块创建 location 级配置。 - 调用时机:解析每个
location块时。 - 特点:一个
server可包含多个location,每个都有独立配置。
8. merge_loc_conf
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
- 作用:将上级配置(可能是 server 或另一个 location)合并到当前 location 配置。
- 参数:
prev:父级配置(可能是 server conf 或嵌套 location 的外层 conf)conf:当前 location 的配置
- 调用时机:
location块解析完成后。 - 合并策略:同
merge_srv_conf,但层级更深(main → server → location → nested location)
🔁 合并顺序示例:
http { my_param 1; // main server { my_param 2; // server overrides main location /a { my_param 3; // location overrides server } } }在
/a的merge_loc_conf中,prev是 server conf(值=2),conf是 loc conf(值=3),若 loc 未设,则继承 2。
总结:配置层级与调用顺序
| 阶段 | 函数 | 调用次数 | 说明 |
|---|---|---|---|
| 预处理 | preconfiguration |
1 次 | HTTP 配置开始前 |
| 创建 main | create_main_conf |
1 次 | 创建 http 级配置 |
| 初始化 main | init_main_conf |
1 次 | 验证/完善 main 配置 |
| 创建 server | create_srv_conf |
每个 server 一次 |
|
| 合并 server | merge_srv_conf |
每个 server 一次 |
main → server |
| 创建 location | create_loc_conf |
每个 location 一次 |
|
| 合并 location | merge_loc_conf |
每个 location 一次 |
server → location |
| 后处理 | postconfiguration |
1 次 | 所有配置解析完毕后 |
实际开发建议
- 所有
create_*_conf函数:只做内存分配和默认值设置(用NGX_CONF_UNSET表示未设置)。 - 所有
merge_*_conf函数:实现继承逻辑,最后赋予真正默认值。 postconfiguration是注册 handler 的黄金位置。- 如果模块不需要某层配置(如无 server 级参数),可设对应函数为
NULL,但 Nginx 仍可能调用,所以通常提供空实现更安全。 - 使用
NGX_CONF_UNSET,NGX_CONF_UNSET_PTR,NGX_CONF_UNSET_SIZE等宏来标记“未设置”。
示例:一个最小可行的 ngx_http_module_t
static ngx_http_module_t ngx_http_my_module_ctx = {
NULL, /* preconfiguration */
ngx_http_my_module_init, /* postconfiguration */
ngx_http_my_module_create_main_conf, /* create_main_conf */
ngx_http_my_module_init_main_conf, /* init_main_conf */
NULL, /* create_srv_conf */
NULL, /* merge_srv_conf */
ngx_http_my_module_create_loc_conf, /* create_loc_conf */
ngx_http_my_module_merge_loc_conf /* merge_loc_conf */
};
通过这个结构体,Nginx 实现了高度模块化、配置继承、阶段化初始化的架构,使得第三方模块可以无缝集成到核心流程中,而无需修改 Nginx 主干代码。这是 Nginx 模块系统设计的精髓所在。
五、配置级别
在 Nginx 配置中,配置级别(Contexts) 是指指令可以被放置的逻辑层级或作用域。不同指令只能出现在特定的上下文中。以下是 Nginx 官方文档定义的所有标准配置级别(上下文),按层次结构从外到内排列:
✅ 1. main(主/全局上下文)
- 位置:配置文件最顶层,不在任何块内。
- 作用范围:整个 Nginx 实例。
- 典型指令:
userworker_processeserror_logpidworker_rlimit_nofiledaemonmaster_process
⚠️ 此上下文不能包含其他块(如
server、location),但可以包含events和http。
✅ 2. events
- 位置:只能在
main上下文中。 - 作用:配置连接处理(事件驱动模型)。
- 典型指令:
worker_connectionsuse(如epoll,kqueue)multi_acceptaccept_mutex
📌 一个配置文件中只能有一个
events块。
✅ 3. http
- 位置:只能在
main上下文中。 - 作用:定义 HTTP 服务器相关配置。
- 可包含:
upstream、map、geo、server等块。 - 典型指令:
includesendfiletcp_nopushkeepalive_timeoutgziplog_formataccess_logclient_max_body_size
📌 一个配置文件中通常只有一个
http块(虽然语法允许多个,但不推荐)。
✅ 4. mail(仅限 Nginx 邮件代理模块)
- 位置:在
main上下文中(与http同级)。 - 作用:配置 IMAP/POP3/SMTP 代理。
- 可包含:
server块(邮件协议用)。 - 注意:需编译时启用
--with-mail模块。
❗ 如果你只用 Nginx 做 Web 服务器,通常不会用到
✅ 5. stream(TCP/UDP 反向代理)
- 位置:在
main上下文中(与http同级)。 - 作用:用于四层(L4)负载均衡,代理 TCP/UDP 流量(如 MySQL、Redis、DNS)。
- 可包含:
server、upstream块。 - 典型指令:
proxy_passproxy_timeoutlisten(指定端口和协议)
🔧 需要
--with-stream模块(现代发行版默认包含)。
✅ 6. server
- 出现位置:
- 在
http块中 → 用于 HTTP 虚拟主机 - 在
mail块中 → 用于邮件服务 - 在
stream块中 → 用于 TCP/UDP 服务
- 在
- 作用:定义一个虚拟主机或监听服务。
- 典型指令(HTTP 中):
listenserver_namerootindexssl_certificatereturn,rewrite
📌 这是 Nginx 虚拟主机的核心单元。
✅ 7. location
- 位置:只能在
http→server块中(即 HTTP 的 server 内)。 - 作用:匹配 URI 路径,定义请求处理逻辑。
- 匹配方式:前缀匹配、正则匹配、精确匹配等。
- 典型指令:
proxy_passfastcgi_passaliastry_filesdeny/allow
❗
location不能出现在stream或server中。
✅ 8. upstream
- 位置:在
http或stream块中(不能在server内)。 - 作用:定义后端服务器组,用于负载均衡。
- 典型指令:
server(upstream 内部的 server 指令,不是 server 块!)least_connip_hashkeepalive
upstream backend {
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
✅ 9. map
- 位置:在
http块中。 - 作用:创建变量映射(基于其他变量的值)。
- 示例:
map $http_user_agent $is_mobile { default 0; "~*mobile" 1; }
✅ 10. geo
- 位置:在
http块中。 - 作用:根据客户端 IP 地址创建变量(常用于地域控制)。
- 示例:
geo $country { default ZZ; 10.0.0.0/8 US; 192.168.0.0/16 CN; }
✅ 11. limit_req_zone / limit_conn_zone
- 位置:在
http块中。 - 作用:定义限流/限连区域(变量 + 共享内存区)。
- 配合指令:
limit_req、limit_conn(用在server或location中)。
✅ 12. if
- 位置:可在
server或location中(不推荐在http中使用)。 - 注意:
if在 Nginx 中有陷阱(如重写上下文问题),应谨慎使用。 - 常见用途:条件判断(但优先考虑
map或try_files)。
✅ 13. 其他特殊上下文(较少见)
| 上下文 | 说明 |
|---|---|
split_clients |
用于 A/B 测试,基于变量分流 |
types |
定义 MIME 类型(通常在 http 中) |
charset_map |
字符集转换映射 |
perl / perl_set |
Perl 模块集成(需编译支持) |
📌 总结:Nginx 主要配置级别层级图
main
├── events
├── http
│ ├── upstream
│ ├── map
│ ├── geo
│ ├── server
│ │ └── location
│ │ └── if (谨慎)
│ └── ...
├── stream
│ ├── upstream
│ └── server
└── mail
└── server
💡 每个指令的可用上下文可在 Nginx 官方文档 中查到,例如
proxy_pass只能在location、if in location、limit_except中使用。
总结
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)