🏗️ Master-Worker 架构
┌─────────────────────────────────────────────────────────────────┐
│ Master Process │
│ (主进程 - 管理员) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 读取配置 │ │ 管理 Worker │ │ 平滑重启 │ │
│ │ 验证配置 │ │ 进程状态 │ │ 热升级 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Worker Process │ │ Worker Process │ │ Worker Process │
│ (工作进程) │ │ (工作进程) │ │ (工作进程) │
│ ┌────────────┐ │ │ ┌────────────┐ │ │ ┌────────────┐ │
│ │ Event Loop │ │ │ │ Event Loop │ │ │ │ Event Loop │ │
│ │ 事件循环 │ │ │ │ 事件循环 │ │ │ │ 事件循环 │ │
│ └─────┬──────┘ │ │ └─────┬──────┘ │ │ └─────┬──────┘ │
│ │ │ │ │ │ │ │ │
│ ┌─────▼──────┐ │ │ ┌─────▼──────┐ │ │ ┌─────▼──────┐ │
│ │ 处理连接 │ │ │ │ 处理连接 │ │ │ │ 处理连接 │ │
│ │ 处理请求 │ │ │ │ 处理请求 │ │ │ │ 处理请求 │ │
│ └────────────┘ │ │ └────────────┘ │ │ └────────────┘ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
└────────────────────┼────────────────────┘
│
┌──────────────┴──────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ 客户端 │ │ 后端 │ │ 文件系统│
│ Clients│ │ Server │ │ Files │
└────────┘ └────────┘ └────────┘
💡 架构特点:
- Master 进程 - 不处理客户端请求,只负责管理职责
- Worker 进程 - 对等关系,独立处理请求,无共享状态
- 事件驱动 - 每个 Worker 使用异步非阻塞 I/O
- 无锁设计 - 进程间无需锁,减少上下文切换
Master 进程职责
| 职责 | 说明 | 触发条件 |
|---|---|---|
| 读取和验证配置 | 读取 nginx.conf 并验证语法 | 启动/重载配置 |
| 绑定端口 | 创建监听套接字 | 启动/热升级 |
| 管理 Worker | 启动、停止、重启 Worker 进程 | 启动/配置变更 |
| 平滑重启 | 发送信号重新加载配置 | HUP 信号 |
| 热升级 | 不中断服务升级 Nginx 二进制 | USR2 信号 |
| 日志轮转 | 重新打开日志文件 | USR1 信号 |
Worker 进程职责
| 职责 | 说明 | 特点 |
|---|---|---|
| 处理连接 | 接受并处理客户端连接 | 异步非阻塞 |
| 执行模块逻辑 | 运行 HTTP、Stream 等模块代码 | 按配置执行 |
| I/O 操作 | 读写网络、文件系统 | 事件驱动 |
| 缓存管理 | 管理代理缓存、FastCGI 缓存 | 进程内缓存 |
| 日志记录 | 写入访问日志和错误日志 | 缓冲写入 |
🔄 事件驱动模型
Worker 进程
启动
启动
→
初始化
创建连接池
创建连接池
→
注册事件
监听套接字
监听套接字
→
事件循环
Event Loop
Event Loop
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Client │ │ epoll │ │ Worker │ │ Backend │ │ File │
│ │ │ (内核) │ │ │ │ Server │ │ System │
└────┬────┘ └────┬─────┘ └────┬────┘ └────┬────┘ └────┬────┘
│ │ │ │ │
│ TCP Connect │ │ │ │
│───────────────>│ │ │ │
│ │ EPOLLIN 事件 │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
│ │ │ accept() │ │
│ │ │ 接受连接 │ │
│ │ │ │ │
│ HTTP Request │ │ │ │
│───────────────>│ │ │ │
│ │ EPOLLIN 事件 │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
│ │ │ 读取请求 │ │
│ │ │ 解析头部 │ │
│ │ │ │ │
│ │ │ 匹配 location │ │
│ │ │ │ │
│ │ │ proxy_pass │ │
│ │ │───────────────>│ │
│ │ │ │ │
│ │ EPOLLOUT 事件 │ │ │
│ │<───────────────│ │ │
│ │ │ │ │
│ │ │ 读取后端响应 │ │
│ │<───────────────│ │ │
│ │ │ │ │
│ HTTP Response │ │ │ │
│<───────────────│ │ │ │
│ │ │ │ │
│ │ │ 记录日志 │ │
│ │ │ 关闭连接 │ │
│ │ │ │ │
事件处理流程
1. 事件注册
Worker 启动时,将监听套接字注册到事件多路复用器(epoll/kqueue)
2. 事件等待
调用 epoll_wait() 阻塞等待事件发生,超时时间由配置决定
3. 事件分发
事件发生后,根据文件描述符找到对应的连接和回调函数
4. 事件处理
执行回调函数处理请求,可能是读取、写入或关闭连接
5. 事件完成
处理完成后,可能注册新的事件(如写事件)或关闭连接
事件多路复用方法对比
| 方法 | 操作系统 | 性能 | 特点 |
|---|---|---|---|
| epoll | Linux 2.6+ | 最优 | 红黑树存储,O(1) 事件查找,支持边缘触发 |
| kqueue | FreeBSD, macOS | 优秀 | BSD 系统原生,功能丰富 |
| /dev/poll | Solaris, AIX | 良好 | 内核级轮询,性能稳定 |
| poll | 跨平台 | 一般 | 线性扫描,连接数多时性能下降 |
| select | 跨平台 | 较差 | 有文件描述符数量限制(通常 1024) |
💡 配置建议:
# 自动选择最佳事件方法
events {
use epoll; # Linux 下推荐显式指定
# 每个 Worker 的最大连接数
worker_connections 10240;
# 接受多个连接
multi_accept on;
# 使用互斥锁(高并发时建议关闭)
accept_mutex off;
}
🧩 模块系统架构
┌─────────────────────────────────────────────────────────────┐
│ Nginx 模块系统架构图 │
└─────────────────────────────────────────────────────────────┘
【核心模块 Core Modules】(必选,无法禁用)
├── ngx_core_module (核心配置)
├── ngx_errlog_module (错误日志)
├── ngx_conf_module (配置解析)
├── ngx_events_module (事件处理)
├── ngx_event_core_module (事件核心)
├── ngx_regex_module (正则表达式)
└── ngx_openssl_module (SSL/TLS 支持)
【HTTP 模块 HTTP Modules】
├── 标准模块 (默认编译)
│ ├── ngx_http_core_module (HTTP 核心)
│ ├── ngx_http_upstream_module (负载均衡)
│ ├── ngx_http_proxy_module (反向代理)
│ ├── ngx_http_fastcgi_module (FastCGI)
│ ├── ngx_http_gzip_module (压缩)
│ ├── ngx_http_ssl_module (HTTPS)
│ ├── ngx_http_v2_module (HTTP/2)
│ ├── ngx_http_v3_module (HTTP/3)
│ ├── ngx_http_limit_req_module (请求限流)
│ ├── ngx_http_limit_conn_module (连接限制)
│ ├── ngx_http_auth_basic_module (基本认证)
│ ├── ngx_http_rewrite_module (URL 重写)
│ └── ngx_http_log_module (访问日志)
│
└── 可选模块 (需编译时启用)
├── ngx_http_stub_status_module (状态监控)
├── ngx_http_sub_module (内容替换)
├── ngx_http_dav_module (WebDAV)
├── ngx_http_geoip_module (GeoIP)
├── ngx_http_lua_module (Lua 脚本) ★
└── ngx_http_cache_purge_module (缓存清除) ★
【邮件代理模块 Mail Modules】
├── ngx_mail_core_module
├── ngx_mail_smtp_module
├── ngx_mail_pop3_module
├── ngx_mail_imap_module
└── ngx_mail_ssl_module
【TCP/UDP代理模块 Stream Modules】
├── ngx_stream_core_module
├── ngx_stream_proxy_module
├── ngx_stream_ssl_module
└── ngx_stream_upstream_module
★ 第三方模块
模块类型与处理阶段
| 模块类型 | 处理阶段 | 典型模块 | 指令示例 |
|---|---|---|---|
| 配置模块 | 启动时 | ngx_core_module | worker_processes |
| 事件模块 | 运行时 | ngx_event_core_module | worker_connections |
| 处理阶段模块 | 请求处理 | ngx_http_access_module | allow, deny |
| 内容生成模块 | CONTENT 阶段 | ngx_http_proxy_module | proxy_pass |
| 过滤器模块 | 响应输出 | ngx_http_gzip_module | gzip |
| 负载均衡模块 | 上游选择 | ngx_http_upstream_module | upstream |
📦 模块查看方法:
# 查看已编译的模块 nginx -V # 输出示例 nginx version: nginx/1.24.0 built by gcc ... configure arguments: --with-http_ssl_module --with-http_v2_module ...
⚡ 高性能设计原理
多进程 vs 多线程模型对比
| 特性 | Nginx (多进程) | 传统服务器 (多线程) |
|---|---|---|
| 进程/线程关系 | Worker 进程相互独立 | 线程共享进程资源 |
| 锁竞争 | 无需锁(无共享状态) | 需要互斥锁保护共享资源 |
| 故障隔离 | 单个 Worker 崩溃不影响其他 | 线程崩溃可能导致整个进程崩溃 |
| 内存使用 | 进程间内存独立 | 线程共享内存空间 |
| 扩展性 | 多核 CPU 友好 | 受 GIL 等限制 |
| 调试难度 | 相对简单 | 死锁、竞态条件复杂 |
内存池设计
┌─────────────────────────────────────────────────────────────┐
│ Nginx 内存池结构 │
├─────────────────────────────────────────────────────────────┤
│ ngx_pool_t (内存池头) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ d = ngx_pool_data_t │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ 已分配内存块 1 (ngx_pool_large_t) │ │ │
│ │ │ - 大内存分配(> 4KB)链表 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ 已分配内存块 2 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ current ──> 当前小块分配位置 │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │ │ │
│ │ │ 已使用 空闲空间 │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ max = 4096 bytes (单次分配上限) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ cleanup ──> 清理回调函数链表 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ cleanup handler: close_file │ │
│ │ cleanup handler: free_memory │ │
│ │ cleanup handler: destroy_temp_file │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
内存分配策略:
├── 小内存 (≤ 4KB): 从 pool->d.current 分配,指针移动
└── 大内存 (> 4KB): 单独分配,加入 large 链表
零拷贝技术
| 技术 | 系统调用 | 数据拷贝次数 | 说明 |
|---|---|---|---|
| 传统 I/O | read + write | 4 次拷贝 | 磁盘→内核→用户→内核→网卡 |
| mmap | mmap + write | 3 次拷贝 | 内存映射减少一次拷贝 |
| sendfile | sendfile | 2 次拷贝 | 内核态直接传输 |
| sendfile + TCP_CORK | sendfile + setsockopt | 2 次拷贝 | 延迟发送,合并小包 |
💡 零拷贝配置:
http {
# 启用 sendfile 零拷贝
sendfile on;
# 启用 tcp_nopush,配合 sendfile 使用
tcp_nopush on;
# 启用 tcp_nodelay,禁用 Nagle 算法
tcp_nodelay on;
# sendfile 单次最大传输量
sendfile_max_chunk 2m;
}
🔗 连接处理机制
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐
│ Client │ │ Listen │ │ Worker │ │ Free │
│ │ │ Socket │ │ Pool │ │ List │
└────┬────┘ └────┬─────┘ └────┬────┘ └────┬────┘
│ │ │ │
│ SYN │ │ │
│───────────────>│ │ │
│ │ │ │
│ SYN-ACK │ │ │
│<───────────────│ │ │
│ │ │ │
│ ACK │ │ │
│───────────────>│ │ │
│ │ │ │
│ │ accept() │ │
│ │───────────────>│ │
│ │ │ │
│ │ │ 从空闲链表获取 │
│ │ │ ngx_connection │
│ │ │───────────────>│
│ │ │ │
│ │ │ 初始化连接 │
│ │ │ - 设置回调 │
│ │ │ - 注册读事件 │
│ │ │ │
│ HTTP Request │ │ │
│───────────────>│ │ │
│ │ │ │
│ │ 读事件触发 │ │
│ │───────────────>│ │
│ │ │ │
│ │ │ 读取并解析请求 │
│ │ │ │
│ │ │ 处理请求 │
│ │ │ │
│ HTTP Response │ │ │
│<───────────────│ │ │
│ │ │ │
│ │ │ 连接回收 │
│ │ │ (keepalive) │
│ │ │ │
连接状态流转
FREE
空闲状态
空闲状态
→
ACCEPT
接受连接
接受连接
→
READ
读取请求
读取请求
→
PROCESS
处理请求
处理请求
→
WRITE
写入响应
写入响应
→
KEEPALIVE
保持连接
保持连接
↺
FREE
回收到空闲链表
回收到空闲链表
连接池配置
| 指令 | 默认值 | 说明 | 调优建议 |
|---|---|---|---|
worker_connections |
1024 | 每个 Worker 最大连接数 | 根据内存和负载调整,建议 10240+ |
worker_rlimit_nofile |
- | Worker 最大文件描述符 | 应 ≥ worker_connections × 2 |
keepalive_timeout |
75s | 长连接超时 | 根据业务调整,API 可设短些 |
keepalive_requests |
100 | 长连接最大请求数 | 建议 1000+ 减少握手 |
keepalive_time |
∞ | 长连接最大使用时间 | 1.19.10+ 新增,防止连接老化 |
📊 配置加载与热更新
Master
接收信号
接收信号
→
读取配置
nginx.conf
nginx.conf
→
验证配置
语法检查
语法检查
→
成功?
→
通知 Worker
发送信号
发送信号
→
Worker 重启
平滑过渡
平滑过渡
信号处理
| 信号 | 发送给 | 作用 | 命令示例 |
|---|---|---|---|
HUP |
Master | 重新加载配置 | nginx -s reload |
USR1 |
Master | 重新打开日志文件(日志轮转) | kill -USR1 $(cat nginx.pid) |
USR2 |
Master | 热升级(启动新 Master) | kill -USR2 $(cat nginx.pid) |
WINCH |
Master | 优雅关闭 Worker(升级后) | kill -WINCH $(cat nginx.pid.oldbin) |
TERM |
Master/Worker | 快速关闭 | nginx -s stop |
QUIT |
Master/Worker | 优雅关闭(完成当前请求) | nginx -s quit |
🔄 热升级流程:
# 1. 备份旧二进制 sudo cp /usr/sbin/nginx /usr/sbin/nginx.old # 2. 替换新二进制 sudo cp nginx-new /usr/sbin/nginx # 3. 发送 USR2 信号,启动新 Master sudo kill -USR2 $(cat /var/run/nginx.pid) # 4. 验证新版本 ps aux | grep nginx # 5. 优雅关闭旧 Worker sudo kill -WINCH $(cat /var/run/nginx.pid.oldbin) # 6. 确认无误后关闭旧 Master sudo kill -QUIT $(cat /var/run/nginx.pid.oldbin) # 如需回滚 sudo kill -USR2 $(cat /var/run/nginx.pid) sudo kill -WINCH $(cat /var/run/nginx.pid.oldbin)
📈 性能调优参数
核心参数配置
| 参数类别 | 指令 | 推荐值 | 说明 |
|---|---|---|---|
| 进程配置 | worker_processes |
auto |
自动检测 CPU 核心数 |
worker_rlimit_nofile |
65535 | 最大文件打开数 | |
worker_connections |
10240-65535 | 每 Worker 连接数 | |
| 网络优化 | sendfile |
on |
启用零拷贝 |
tcp_nopush |
on |
TCP 包优化 | |
tcp_nodelay |
on |
禁用 Nagle 算法 | |
keepalive_timeout |
65s | 长连接超时 | |
| 缓存优化 | open_file_cache |
max=10000 inactive=20s |
文件缓存 |
open_file_cache_valid |
60s | 缓存检查间隔 | |
open_file_cache_min_uses |
2 | 最小使用次数 | |
| 缓冲优化 | client_body_buffer_size |
16k-128k | 请求体缓冲 |
proxy_buffer_size |
8k-16k | 代理响应头缓冲 |
💡 完整优化配置示例:
# 进程配置
worker_processes auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 65535;
multi_accept on;
accept_mutex off;
}
http {
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 连接优化
keepalive_timeout 65;
keepalive_requests 1000;
keepalive_time 1h;
# 文件缓存
open_file_cache max=10000 inactive=20s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
# 缓冲配置
client_body_buffer_size 128k;
client_max_body_size 100m;
# 代理缓冲
proxy_buffer_size 16k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
}