从架构原理到生产实践的完整指南 — 涵盖高性能 Web 服务器、反向代理与负载均衡
📋 目录索引
一、Nginx 概述
1.1 什么是 Nginx?
Nginx 简介
Nginx(发音为 "engine-x")是一个开源的、高性能的 HTTP 和反向代理服务器,同时也提供了 IMAP/POP3/SMTP 邮件代理服务。它由俄罗斯程序员 Igor Sysoev 于 2002 年开始开发,2004 年正式发布,旨在解决 C10K 问题(同时处理 10,000 个并发连接)。
💡 核心特点:
Nginx 采用异步非阻塞的事件驱动架构,相比传统的 Apache 进程/线程模型,在高并发场景下具有显著的性能优势和更低的资源消耗。
主要功能
🌐 Web 服务器
高性能静态文件服务,支持 HTTP/2、HTTPS、gzip 压缩等
🔄 反向代理
将客户端请求转发到后端服务器,隐藏后端拓扑
⚖️ 负载均衡
支持多种负载均衡算法,分发流量到多个后端
📦 静态文件服务
高效的静态内容缓存与分发
🔐 SSL/TLS 终端
SSL 卸载、证书管理、HTTPS 加速
📊 缓存代理
反向代理缓存,减少后端压力
市场份额
根据 W3Techs 的统计数据,Nginx 在全球活跃网站中的使用率超过 30%,在流量最大的 1000 个网站中使用率超过 40%,是全球使用最广泛的 Web 服务器之一。
| 特性 | Nginx | Apache |
|---|---|---|
| 架构模型 | 事件驱动(异步非阻塞) | 进程/线程(多进程模型) |
| 并发连接 | 数万级轻松处理 | 数千级(受进程限制) |
| 内存消耗 | 极低(每连接数 KB) | 较高(每连接数 MB) |
| 静态文件处理 | 极快 | 较快 |
| 动态内容处理 | 需要配合 FastCGI/uWSGI | 内置模块支持 |
| 配置复杂度 | 简洁清晰 | 功能丰富但较复杂 |
1.2 Nginx 版本与许可
版本类型
- Nginx OSS(开源版):采用 2-clause BSD 许可证,完全免费开源
- Nginx Plus(商业版):F5 公司(2019 年收购 Nginx)提供的企业级版本,包含额外功能和技术支持
- Nginx 版本命名规则:偶数版本号(如 1.24、1.26)为稳定版,奇数版本号(如 1.25、1.27)为开发版
版本发布策略
Nginx 遵循大约每年发布一个稳定主版本的节奏,每个稳定版本会维护约 18 个月的安全更新。建议生产环境使用最新的稳定版本。
ℹ️ 版本选择建议:
截至 2026 年,推荐使用 Nginx 1.26.x 或 1.28.x 稳定版本。
二、软件设计架构
2.1 总体架构设计
架构设计理念
Nginx 的架构设计核心思想是事件驱动 + 多进程模型,这是它能够高效处理大量并发连接的关键。与 Apache 的每请求一个进程/线程不同,Nginx 使用了 reactor 模式,通过少量的 worker 进程即可处理成千上万的并发连接。
┌─────────────────────────────────────────────────────────────────┐ │ Nginx 架构总览 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Master │ │ Worker 1 │ │ Worker N │ │ │ │ Process │────▶│ Process │ │ Process │ │ │ │ (管理进程) │ │ (工作进程) │ │ (工作进程) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ │ ┌─────┴─────┐ ┌─────┴─────┐ │ │ │ │ Event │ │ Event │ │ │ │ │ Loop │ │ Loop │ │ │ │ └─────┬─────┘ └─────┬─────┘ │ │ │ │ │ │ │ ┌──────┴──────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ │ │ Cache │ │ epoll/ │ │ epoll/ │ │ │ │ Manager │ │ kqueue │ │ kqueue │ │ │ └─────────────┘ └───────────┘ └───────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
核心组件说明
| 组件 | 职责 | 数量 |
|---|---|---|
| Master Process(主进程) | 读取和验证配置文件、创建/管理 worker 进程、发送信号、日志轮转管理 | 1 |
| Worker Process(工作进程) | 处理实际的客户端连接、执行事件循环、处理请求 | 通常等于 CPU 核心数 |
| Cache Loader(缓存加载器) | 启动时将缓存元数据加载到内存中 | 1(按需) |
| Cache Manager(缓存管理器) | 定期检查缓存条目有效性,清理过期条目 | 1(按需) |
2.2 Master-Worker 进程模型详解
Master Process(主进程)
主进程以 root 权限运行,负责以下工作:
- 读取配置文件:解析 nginx.conf 及其引用的配置文件
- 创建 worker 进程:fork 出指定数量的 worker 子进程
- 信号处理:
- SIGTERM/SIGINT - 快速关闭
- SIGQUIT - 优雅关闭
- SIGHUP - 重新加载配置文件
- SIGUSR1 - 重新打开日志文件
- SIGUSR2 - 平滑升级(热重启)
- 监控 worker 进程:当 worker 异常退出时自动重启新的 worker
- 特权操作:绑定端口、创建 PID 文件等需要 root 权限的操作
Worker Process(工作进程)
工作进程以非特权用户身份运行(通常是 nginx 或 www-data),负责:
- 事件循环:每个 worker 独立运行自己的事件循环
- 连接处理:处理 TCP/UDP 连接的建立、数据传输、关闭
- 请求处理:解析 HTTP 请求,调用相应的处理模块
- 负载均衡竞争:多个 worker 通过 accept_mutex 或 reuseport 竞争新连接
┌─────────────────────────────────────────────────────────────┐ │ Master 进程管理流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ nginx -c /etc/nginx/nginx.conf │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ fork() │ │ │ │ Master │ │ │ └──────┬───────┘ │ │ │ │ │ ┌────┼────┬────────┐ │ │ ▼ ▼ ▼ ▼ │ │ ┌───┐┌───┐┌───┐ ┌───┐ │ │ │ W1││ W2││ W3│ │ Wn│ ← Worker 进程(非特权用户) │ │ └───┘└───┘└───┘ └───┘ │ │ │ │ 信号传递: Master ──signal──▶ Worker │ │ Worker 退出: Worker ──exit──▶ Master (自动重启) │ │ │ └─────────────────────────────────────────────────────────────┘
进程间通信(IPC)
Nginx 使用以下方式进行进程间通信:
- Unix Signal(信号):主进程向 worker 发送控制信号
- Unix Domain Socket:用于 worker 之间的通信和共享数据
- 共享内存:用于 worker 之间共享配置、状态等信息
- 文件锁:用于 accept_mutex 互斥机制
2.3 事件驱动模型(Event-Driven)
事件驱动架构核心
Nginx 使用异步非阻塞 I/O + 多路复用的事件驱动模型,这是其高性能的关键所在。与传统同步阻塞 I/O 不同,事件驱动模型不会因为等待 I/O 而阻塞整个进程。
🔑 关键概念:
每个 worker 进程在同一时间只运行一个事件循环,但可以通过非阻塞 I/O 同时处理成千上万个连接。
I/O 多路复用机制
Nginx 支持多种操作系统提供的高效 I/O 多路复用机制:
| 操作系统 | I/O 多路复用机制 | 特点 |
|---|---|---|
| Linux | epoll | 时间复杂度 O(1),适合大规模连接 |
| FreeBSD/macOS | kqueue | 高效的 BSD 系统事件通知 |
| Solaris | /dev/poll | Solaris 特有 |
| 所有平台 | select/poll | 通用但性能较差,作为备选 |
事件处理流程
┌─────────────────────────────────────────────────────┐ │ Worker 事件循环流程 │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ │ │ │ 等待 │◄─────────────────────────┐ │ │ │ 事件 │ │ │ │ └────┬─────┘ │ │ │ │ (epoll_wait 返回) │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ 遍历 │ │ │ │ │ 就绪事件│ │ │ │ └────┬─────┘ │ │ │ │ │ │ │ ▼ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ │ 处理 │────▶│ 处理 │────... │ │ │ │ 事件 A │ │ 事件 B │ │ │ │ └────┬─────┘ └──────────┘ │ │ │ │ │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ 检查 │──── 没有更多事件 ────────┘ │ │ │ 定时器 │ │ │ └──────────┘ │ │ │ └─────────────────────────────────────────────────────┘
连接状态机
每个连接在 Nginx 中被表示为一个 ngx_connection_t 结构体,通过状态机管理其生命周期:
接受连接
→
读取请求头
→
解析请求
→
处理请求
→
发送响应
→
关闭/保持
每个阶段的处理函数都注册为事件回调,当 I/O 就绪时自动触发,避免了线程切换和锁竞争的开销。
2.4 内存管理机制
内存池(Memory Pool)
Nginx 使用了自定义的内存池管理系统,避免了频繁调用 malloc/free 带来的性能开销和内存碎片问题。
- 池化分配:预先分配一块大内存,后续从小块中分配
- 自动释放:请求处理完成后,整个内存池一次性释放
- 对齐分配:内存按指针对齐,提高 CPU 缓存命中率
- 大内存处理:超过池大小的分配使用系统 malloc,记录在链表中随池释放
内存池结构
struct ngx_pool_s {
ngx_pool_data_t d; /* 内存池数据 */
size_t max; /* 最大块大小 */
ngx_pool_t *current; /* 当前分配池 */
ngx_chain_t *chain; /* 大内存链表 */
ngx_pool_large_t *large; /* 大内存分配列表 */
ngx_pool_cleanup_t *cleanup; /* 清理回调 */
ngx_log_t *log; /* 日志 */
};
缓冲区管理
Nginx 使用 ngx_buf_t 结构体管理数据缓冲区,支持:
- 内存缓冲区:数据存储在内存中
- 文件缓冲区:数据引用磁盘文件,使用 sendfile 零拷贝传输
- 链式缓冲区:通过 ngx_chain_t 将多个缓冲区串联
⚡ Zero-Copy(零拷贝):
Nginx 在发送静态文件时,使用 sendfile() 系统调用,数据直接从磁盘文件传输到网络套接字,避免了内核空间到用户空间的拷贝,极大提升了性能。
2.5 请求处理流水线
11 个处理阶段(Phases)
Nginx 将 HTTP 请求的处理过程分为 11 个阶段(Phases),每个阶段执行特定的功能,模块可以在对应阶段注册处理函数:
| 阶段 | 名称 | 功能 |
|---|---|---|
| 1 | POST_READ | 读取请求后首先执行,如获取客户端真实IP |
| 2 | SERVER_REWRITE | server 级别的 URL 重写 |
| 3 | FIND_CONFIG | 根据 URI 查找匹配的 location(不可插入模块) |
| 4 | REWRITE | location 级别的 URL 重写 |
| 5 | POST_REWRITE | URL 重写后重新查找 location(不可插入模块) |
| 6 | PREACCESS | 访问控制前准备,如限流、连接限制 |
| 7 | ACCESS | 访问控制,如 allow/deny 规则 |
| 8 | POST_ACCESS | 访问控制后处理(如 satisfy any) |
| 9 | PRECONTENT | 内容处理前的准备 |
| 10 | CONTENT | 生成响应内容(核心阶段) |
| 11 | LOG | 记录日志 |
请求进入 │ ▼ POST_READ ──▶ SERVER_REWRITE ──▶ FIND_CONFIG ──▶ REWRITE │ ┌─────────────────────────────────────────────────┘ ▼ POST_REWRITE ──▶ PREACCESS ──▶ ACCESS ──▶ POST_ACCESS │ ┌─────────────────────────────────────────────────┘ ▼ PRECONTENT ──▶ CONTENT ──▶ LOG ──▶ 请求完成
2.6 配置解析与继承机制
配置解析流程
- 配置文件读取:主进程读取 nginx.conf
- 词法分析:将配置文件解析为 token 流
- 语法分析:构建配置命令树(command tree)
- 命令执行:按照作用域依次执行配置指令
- 配置合并:将不同级别的配置进行合并
- NGX_MAIN_CONF:全局配置(如 worker_processes)
- NGX_HTTP_MAIN_CONF:HTTP 主配置
- NGX_HTTP_SRV_CONF:Server 配置
- NGX_HTTP_LOC_CONF:Location 配置
- NGX_HTTP_UPS_CONF:Upstream 配置
- accept_mutex(传统方式):worker 通过互斥锁竞争 accept 权限,只有获得锁的 worker 才能调用 accept()
- reuseport(推荐方式,Linux 3.9+):内核级别的连接分配,每个 worker 独立监听端口,由内核公平分配连接,性能更优
- 简单指令:指令名 参数;
- 块指令:指令名 { ... }
- 注释:# 注释内容
- 变量:$变量名(如 $remote_addr, $uri)
- = 精确匹配
- ^~ 前缀匹配(优先于正则)
- ~ 或 ~* 正则匹配(按配置文件顺序)
- 普通前缀匹配(选择最长匹配)
- proxy_pass http://backend — 不修改 URI,原始 URI 直接传递
- proxy_pass http://backend/ — 将 location 匹配的部分替换为 /
- 静态编译:模块直接编译到 Nginx 二进制文件中
- 动态加载(Nginx 1.9.11+):使用 load_module 指令动态加载 .so 文件
- 连接数:活跃连接数、等待连接数
- 请求数:QPS、请求成功率
- 状态码分布:2xx/3xx/4xx/5xx 比例
- 响应时间:平均响应时间、P95/P99 延迟
- 带宽使用:入站/出站流量
- 错误率:5xx 错误比例
- 上游健康:后端服务器健康状态
配置继承(Merge)机制
Nginx 的配置具有层级继承关系:
main (全局配置) │ ├── http { } (HTTP 协议级) │ │ │ ├── server { } (虚拟主机级) │ │ │ │ │ └── location { } (URI 路径级) │ │ │ └── upstream { } (上游服务器组) │ ├── events { } (事件处理级) │ ├── mail { } (邮件代理级) │ └── stream { } (TCP/UDP 代理级)
继承规则:子级配置默认继承父级配置,如果子级配置中显式定义了相同的指令,则覆盖父级配置。
配置指令类型
2.7 连接管理与事件通知
连接池
Nginx 预先分配固定数量的连接对象(由 worker_connections 指令控制),所有连接从连接池中获取,用完归还,避免了动态内存分配的开销。
struct ngx_connection_s {
void *data; /* 关联的数据 */
ngx_event_t *read; /* 读事件 */
ngx_event_t *write; /* 写事件 */
ngx_socket_t fd; /* 文件描述符 */
ngx_recv_pt recv; /* 接收函数 */
ngx_send_pt send; /* 发送函数 */
struct sockaddr *sockaddr; /* 对端地址 */
socklen_t socklen;
ngx_str_t addr_text; /* 地址文本 */
/* ... */
};
连接竞争机制
多个 worker 进程监听同一端口时,需要一种机制来协调谁接受新连接:
🚀 性能提示:
在 Linux 3.9+ 环境下,建议启用 reuseport 以获得更好的连接分配性能:
listen 80 reuseport;
三、安装与部署
3.1 Linux 系统安装
Ubuntu/Debian 安装
# 更新软件包索引
sudo apt update
# 安装 Nginx
sudo apt install nginx
# 启动 Nginx
sudo systemctl start nginx
# 设置开机自启
sudo systemctl enable nginx
# 查看状态
sudo systemctl status nginx
使用官方仓库安装(推荐,获取最新版本)
# 安装先决条件
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
# 导入官方签名密钥
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# 添加稳定版仓库
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# 更新并安装
sudo apt update
sudo apt install nginx
CentOS/RHEL/Rocky Linux 安装
# 使用 EPEL 仓库
sudo yum install epel-release
sudo yum install nginx
# 或使用官方仓库,创建 /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
sudo yum install nginx
验证安装
# 检查版本
nginx -v
# 测试配置文件语法
sudo nginx -t
# 输出示例:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
3.2 从源码编译安装
准备工作
# 安装编译工具和依赖
# Ubuntu/Debian
sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
libssl-dev libgd-dev libgeoip-dev libxml2-dev libxslt1-dev
# CentOS/RHEL
sudo yum groupinstall "Development Tools"
sudo yum install pcre-devel zlib-devel openssl-devel gd-devel \
geoip-devel libxml2-devel libxslt-devel
下载并编译
# 下载源码
wget https://nginx.org/download/nginx-1.26.2.tar.gz
tar -zxvf nginx-1.26.2.tar.gz
cd nginx-1.26.2
# 配置编译选项
./configure \
--prefix=/usr/local/nginx \
--sbin-path=/usr/local/nginx/sbin/nginx \
--conf-path=/usr/local/nginx/conf/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/run/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_image_filter_module \
--with-http_geoip_module \
--with-stream \
--with-stream_ssl_module \
--with-threads \
--with-file-aio
# 编译安装
make -j$(nproc)
sudo make install
创建 systemd 服务文件
sudo nano /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
# 重新加载并启用
sudo systemctl daemon-reload
sudo systemctl enable nginx
3.3 Docker 容器化部署
基本使用
# 拉取官方镜像
docker pull nginx:latest
# 运行容器
docker run -d --name nginx \
-p 80:80 \
-p 443:443 \
-v /path/to/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /path/to/conf.d:/etc/nginx/conf.d:ro \
-v /path/to/ssl:/etc/nginx/ssl:ro \
-v /path/to/html:/usr/share/nginx/html:ro \
nginx:latest
Docker Compose 配置
version: '3.8'
services:
nginx:
image: nginx:1.26-alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./conf.d:/etc/nginx/conf.d:ro
- ./ssl:/etc/nginx/ssl:ro
- ./html:/usr/share/nginx/html:ro
- ./logs:/var/log/nginx
restart: unless-stopped
networks:
- webnet
networks:
webnet:
driver: bridge
自定义 Dockerfile
FROM nginx:1.26-alpine
# 复制自定义配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# 复制静态文件
COPY html/ /usr/share/nginx/html/
# 安装额外工具(可选)
RUN apk add --no-cache curl
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
四、配置详解
4.1 配置文件结构
主要配置文件
# /etc/nginx/nginx.conf - 主配置文件
# ===== 全局块 =====
user nginx; # 运行用户
worker_processes auto; # worker 进程数(auto=CPU 核心数)
worker_rlimit_nofile 65535; # 每个 worker 最大打开文件数
error_log /var/log/nginx/error.log warn; # 错误日志
pid /run/nginx.pid; # PID 文件
# ===== events 块 =====
events {
worker_connections 4096; # 每个 worker 最大并发连接数
use epoll; # I/O 多路复用模型
multi_accept on; # 一次接受多个连接
}
# ===== http 块 =====
http {
include /etc/nginx/mime.types; # MIME 类型映射
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# 性能优化
sendfile on; # 启用零拷贝
tcp_nopush on; # 启用 TCP_NOPUSH
tcp_nodelay on; # 启用 TCP_NODELAY
keepalive_timeout 65; # 长连接超时
types_hash_max_size 2048; # 类型哈希表大小
client_max_body_size 50m; # 客户端最大请求体
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json
application/javascript text/xml
application/xml application/xml+rss text/javascript;
# 包含子配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
指令语法
4.2 Server 虚拟主机配置
Server Block 基本结构
server {
# 监听端口和地址
listen 80;
listen [::]:80; # IPv6
listen 443 ssl http2; # HTTPS + HTTP/2
# 服务器名称(支持通配符和正则表达式)
server_name example.com www.example.com;
server_name *.example.com; # 通配符
server_name ~^(?<subdomain>.+)\.example\.com$; # 正则
# 根目录
root /var/www/example.com/html;
# 默认首页
index index.html index.htm index.php;
# 字符集
charset utf-8;
# 访问日志
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# location 块
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server_name 匹配规则
| 匹配类型 | 示例 | 说明 |
|---|---|---|
| 精确匹配 | example.com | 完全匹配域名 |
| 前缀通配符 | *.example.com | 匹配所有子域名 |
| 后缀通配符 | example.* | 匹配所有后缀 |
| 正则表达式 | ~^www\.(.+)\.com$ | 正则匹配(~ 区分大小写,~* 不区分) |
优先级顺序:精确匹配 > 前缀通配符 > 后缀通配符 > 正则表达式
4.3 Location 匹配规则详解
Location 语法
location [=|~|~*|^~|@] /uri { ... }
匹配修饰符
| 修饰符 | 含义 | 示例 |
|---|---|---|
| = | 精确匹配 | location = /api/health |
| ^~ | 前缀匹配(匹配后停止正则搜索) | location ^~ /static/ |
| ~ | 正则匹配(区分大小写) | location ~ \.php$ |
| ~* | 正则匹配(不区分大小写) | location ~* \.(jpg|png|gif)$ |
| @ | 命名 location(用于内部重定向) | location @fallback |
| (无) | 普通前缀匹配 | location /images/ |
匹配优先级(从高到低)
配置示例
# 精确匹配首页
location = / {
root /var/www/html;
index index.html;
}
# 静态文件 - 前缀匹配,不再检查正则
location ^~ /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# 图片文件 - 正则匹配
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# API 路由
location ~ ^/api/v1/ {
proxy_pass http://api_backend;
}
# 所有其他请求
location / {
try_files $uri $uri/ /index.html;
}
⚠️ 常见陷阱:
location 的正则匹配是按配置文件中的顺序匹配的,第一个匹配的正则表达式生效,而非最长匹配。因此应将更具体的正则放在前面。
4.4 常用指令速查
文件服务相关
| 指令 | 作用 | 示例 |
|---|---|---|
| root | 指定文件根目录(会拼接 URI) | root /var/www/html; |
| alias | 指定文件目录(替换 URI) | alias /var/www/static/; |
| index | 默认首页文件列表 | index index.html index.php; |
| try_files | 尝试查找文件,失败时回退 | try_files $uri $uri/ =404; |
| autoindex | 启用目录列表 | autoindex on; |
控制流程指令
| 指令 | 作用 |
|---|---|
| return | 直接返回状态码和/或 URL |
| rewrite | URL 重写(支持正则) |
| if | 条件判断 |
| set | 设置变量 |
| map | 创建变量映射 |
rewrite 指令详解
# 语法: rewrite regex replacement [flag];
# flag 选项:
# last - 停止当前处理,用新 URI 重新匹配 location
# break - 停止当前 rewrite 规则集的处理
# redirect - 返回 302 临时重定向
# permanent - 返回 301 永久重定向
# 示例:
# HTTP 转 HTTPS
rewrite ^(.*)$ https://$host$1 permanent;
# 旧 URL 重定向
rewrite ^/old-page$ /new-page permanent;
# 动态 URL 重写
rewrite ^/user/(\d+)$ /user.php?id=$1 last;
map 指令示例
# 在 http 块中定义
map $http_user_agent $is_mobile {
default 0;
"~*mobile|android|iphone|ipad" 1;
}
map $uri $new_uri {
default $uri;
"~^/blog/(.*)" /articles/$1;
"~^/news/(.*)" /press/$1;
}
# 在 server/location 中使用
server {
if ($is_mobile) {
rewrite ^ /mobile$uri;
}
}
五、反向代理与负载均衡
5.1 反向代理配置
基本反向代理
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
# 传递客户端信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
完整的反向代理配置
server {
listen 80;
server_name app.example.com;
# 代理超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 代理缓冲区
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
# 临时文件(大响应体写入磁盘)
proxy_temp_file_write_size 64k;
proxy_max_temp_file_size 1024m;
# WebSocket 支持
location /ws {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
}
# API 代理
location /api/ {
proxy_pass http://api_servers/; # 注意末尾斜杠
# 错误处理
proxy_intercept_errors on;
error_page 502 503 504 = @fallback;
}
location @fallback {
proxy_pass http://backup_server;
}
}
proxy_pass URL 末尾斜杠的区别
📝 重要区别:
例如:location /api/ 匹配请求 /api/users • 无斜杠:后端收到 /api/users • 有斜杠:后端收到 /users
5.2 Upstream 负载均衡
Upstream 配置
# 定义上游服务器组
upstream backend {
# 负载均衡算法(默认为轮询)
# 可用: ip_hash, hash, least_conn, random
server 192.168.1.10:8080 weight=5; # 权重
server 192.168.1.11:8080 weight=3;
server 192.168.1.12:8080 backup; # 备份服务器
server 192.168.1.13:8080 down; # 标记为下线
# 长连接(与后端保持的连接数)
keepalive 32;
keepalive_timeout 60s;
keepalive_requests 1000;
}
负载均衡算法
轮询(Round Robin)
默认算法,按顺序将请求分配给服务器,支持权重。
upstream backend {
server 10.0.0.1:80;
server 10.0.0.2:80;
}
IP Hash
根据客户端 IP 的 hash 值分配,保证同一客户端始终访问同一服务器(会话保持)。
upstream backend {
ip_hash;
server 10.0.0.1:80;
server 10.0.0.2:80;
}
Least Connections
将请求分配给当前活跃连接数最少的服务器。
upstream backend {
least_conn;
server 10.0.0.1:80;
server 10.0.0.2:80;
}
Hash(自定义键)
基于自定义键值的 hash 分配,适合缓存场景。
upstream backend {
hash $request_uri consistent;
server 10.0.0.1:80;
server 10.0.0.2:80;
}
健康检查
upstream backend {
server 10.0.0.1:80 max_fails=3 fail_timeout=30s;
server 10.0.0.2:80 max_fails=3 fail_timeout=30s;
server 10.0.0.3:80 max_fails=3 fail_timeout=30s;
}
# max_fails=N: 在 fail_timeout 内允许的最大失败次数
# fail_timeout=T: 失败统计的时间窗口,也是服务器被标记不可用后的冷却时间
使用 upstream 的完整配置
upstream app_backend {
least_conn;
server 10.0.0.1:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.0.2:8080 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.0.3:8080 backup;
keepalive 32;
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://app_backend;
# 使用 HTTP/1.1 以支持 keepalive
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
5.3 代理缓存配置
代理缓存
# 在 http 块中定义缓存路径
proxy_cache_path /var/cache/nginx/proxy levels=1:2
keys_zone=my_cache:10m # 共享内存区域名:大小
max_size=10g # 最大缓存大小
inactive=60m # 不活跃条目过期时间
use_temp_path=off; # 不使用临时路径
# 在 server/location 中使用
server {
location / {
proxy_pass http://backend;
# 启用缓存
proxy_cache my_cache;
proxy_cache_valid 200 302 10m; # 200/302 响应缓存 10 分钟
proxy_cache_valid 404 1m; # 404 响应缓存 1 分钟
proxy_cache_valid any 5m; # 其他响应缓存 5 分钟
# 缓存键
proxy_cache_key "$scheme$request_method$host$request_uri";
# 缓存控制
proxy_cache_use_stale error timeout updating http_500 http_502
http_503 http_504;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
# 添加缓存状态头
add_header X-Cache-Status $upstream_cache_status;
# 绕过缓存的条件
proxy_cache_bypass $http_cache_control $cookie_nocache;
proxy_no_cache $http_pragma $http_authorization;
}
}
# $upstream_cache_status 可能的值:
# HIT - 缓存命中
# MISS - 缓存未命中
# EXPIRED - 缓存已过期
# STALE - 返回过期缓存(后端不可用时)
# UPDATING - 缓存正在更新
# BYPASS - 缓存被绕过
FastCGI 缓存(适用于 PHP 等)
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2
keys_zone=php_cache:10m max_size=1g inactive=60m;
server {
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_cache php_cache;
fastcgi_cache_valid 200 10m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout updating;
add_header X-FastCGI-Cache $upstream_cache_status;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
六、SSL/TLS 配置
6.1 HTTPS 基本配置
SSL 证书配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# SSL 证书配置
ssl_certificate /etc/nginx/ssl/example.com.crt; # 证书文件(PEM 格式)
ssl_certificate_key /etc/nginx/ssl/example.com.key; # 私钥文件
# 或使用 ECDSA 证书
# ssl_certificate /etc/nginx/ssl/ecdsa.crt;
# ssl_certificate_key /etc/nginx/ssl/ecdsa.key;
# SSL 协议和加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off; # TLS 1.3 推荐设为 off
# SSL 会话缓存(提升性能)
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off; # 安全起见可关闭
# DH 参数(增强密钥交换安全)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# HSTS (HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# 其他安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 网站内容
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
HTTP 到 HTTPS 重定向
# 方法一:return(推荐,性能更好)
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# 方法二:rewrite
server {
listen 80;
server_name example.com www.example.com;
rewrite ^(.*)$ https://$host$1 permanent;
}
6.2 Let's Encrypt 免费证书配置
使用 Certbot 自动获取证书
# 安装 Certbot 和 Nginx 插件
sudo apt install certbot python3-certbot-nginx # Debian/Ubuntu
sudo yum install certbot python3-certbot-nginx # CentOS/RHEL
# 自动获取证书并配置 Nginx
sudo certbot --nginx -d example.com -d www.example.com
# 仅获取证书(手动配置)
sudo certbot certonly --webroot -w /var/www/html -d example.com
# 使用 DNS 验证(适用于通配符证书)
sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com"
# 测试自动续期
sudo certbot renew --dry-run
# 证书路径(Let's Encrypt 默认)
# 证书: /etc/letsencrypt/live/example.com/fullchain.pem
# 私钥: /etc/letsencrypt/live/example.com/privkey.pem
配合 Certbot 的 Nginx 配置
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Let's Encrypt 验证路径(续期时需要)
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# 其余配置...
location / {
root /var/www/example.com/html;
}
}
server {
listen 80;
server_name example.com www.example.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
生成 DH 参数
# 生成 2048 位 DH 参数(推荐)
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
# 生成 4096 位 DH 参数(更安全但更慢)
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
6.3 HTTP/2 和 HTTP/3 (QUIC) 配置
HTTP/2 配置
server {
listen 443 ssl;
http2 on; # Nginx 1.25.1+ 新语法
# 或旧语法: listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# HTTP/2 特定优化
# 多路复用默认启用,无需额外配置
# 服务器推送(可选)
# http2_push /static/style.css;
# http2_push /static/app.js;
}
HTTP/3 (QUIC) 配置(Nginx 1.25+)
server {
# QUIC/HTTP3 监听
listen 443 quic reuseport;
listen 443 ssl;
http2 on;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 告知客户端支持 HTTP/3
add_header Alt-Svc 'h3=":443"; ma=86400';
location / {
root /var/www/html;
}
}
🌐 HTTP/3 优势:
基于 UDP 的 QUIC 协议,解决了 TCP 的队头阻塞问题,连接建立更快(0-RTT),在弱网环境下性能显著优于 TCP。
七、性能优化
7.1 系统级调优
操作系统内核参数优化
# /etc/sysctl.conf - Linux 内核参数优化
# 文件系统
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
# 网络优化
net.core.somaxconn = 65535 # 监听队列最大长度
net.core.netdev_max_backlog = 65535 # 网络设备积压
net.core.rmem_max = 16777216 # 接收缓冲区最大
net.core.wmem_max = 16777216 # 发送缓冲区最大
net.core.rmem_default = 262144
net.core.wmem_default = 262144
# TCP 优化
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1 # 允许重用 TIME_WAIT 连接
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.ip_local_port_range = 1024 65535
# 连接跟踪
net.netfilter.nf_conntrack_max = 1000000
# 应用修改
# sudo sysctl -p
文件描述符限制
# /etc/security/limits.conf
nginx soft nofile 65535
nginx hard nofile 65535
nginx soft nproc 65535
nginx hard nproc 65535
# 或在 systemd 服务文件中设置
# [Service]
# LimitNOFILE=65535
# LimitNPROC=65535
Nginx 配置中的关键参数
# 全局配置
worker_processes auto; # 等于 CPU 核心数
worker_rlimit_nofile 65535; # 每个 worker 最大文件描述符数
worker_cpu_affinity auto; # CPU 亲和性(自动绑定)
# events 块
events {
worker_connections 4096; # 每 worker 最大并发连接
use epoll; # 最佳 I/O 模型
multi_accept on; # 批量接受连接
accept_mutex off; # 使用 reuseport 时关闭
}
# http 块
http {
sendfile on; # 零拷贝传输
tcp_nopush on; # 合并小数据包
tcp_nodelay on; # 禁用 Nagle 算法
keepalive_timeout 65; # 长连接超时
keepalive_requests 1000; # 单连接最大请求数
# 连接限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
}
7.2 静态文件优化
Sendfile 与零拷贝
# 启用 sendfile(内核直接从文件发送数据到网络)
sendfile on;
# 启用 aio(异步 I/O,适用于大文件)
aio on;
directio 512; # 大于 512 字节的文件使用直接 I/O
Gzip 压缩优化
# 在 http 或 server 块中
gzip on; # 启用 gzip
gzip_vary on; # 添加 Vary: Accept-Encoding 头
gzip_proxied any; # 对所有代理请求压缩
gzip_comp_level 5; # 压缩级别 (1-9),5 是较好的平衡
gzip_min_length 256; # 最小压缩大小(避免压缩小文件)
gzip_buffers 16 8k; # 压缩缓冲区
# 需要压缩的 MIME 类型
gzip_types
text/plain
text/css
text/javascript
text/xml
application/json
application/javascript
application/x-javascript
application/xml
application/xml+rss
application/vnd.ms-fontobject
font/opentype
image/svg+xml
image/x-icon;
浏览器缓存控制
# 静态资源长缓存
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff2?|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# HTML 文件短缓存
location ~* \.html?$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# API 响应不缓存
location /api/ {
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header Pragma "no-cache";
}
Open File Cache
# 缓存文件元数据(减少 stat 系统调用)
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 60s; # 验证缓存有效性的间隔
open_file_cache_min_uses 2; # 文件最少使用次数才缓存
open_file_cache_errors on; # 缓存文件错误(404等)
7.3 限流与流量控制
连接数限制(limit_conn)
# 在 http 块中定义区域
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn_zone $server_name zone=perserver:10m;
# 在 server/location 中使用
server {
# 每个 IP 最多 10 个并发连接
limit_conn addr 10;
# 每个虚拟主机最多 1000 个并发连接
limit_conn perserver 1000;
# 超限返回状态码
limit_conn_status 503;
limit_conn_log_level warn;
}
请求速率限制(limit_req)
# 在 http 块中定义区域
# rate=10r/s 表示每秒 10 个请求
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
# 在 server/location 中使用
server {
# API 限流:突发允许 20 个,无延迟处理
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://api_backend;
}
# 登录接口更严格的限流
location /login {
limit_req zone=login_limit burst=5 nodelay;
proxy_pass http://auth_backend;
}
# 白名单排除
location /admin/ {
# 不应用限流(通过 geo 模块实现白名单)
limit_req zone=api_limit burst=100 nodelay;
}
}
# 使用 geo 模块创建白名单
geo $limit_req {
default 1;
10.0.0.0/8 0; # 内网不限流
192.168.0.0/16 0; # 内网不限流
}
# 条件限流
map $limit_req $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=conditional:10m rate=10r/s;
八、安全加固
8.1 安全基础配置
隐藏版本信息
http {
# 隐藏 Nginx 版本号
server_tokens off;
# 修改 Server 头(需要编译时修改或 More Headers 模块)
more_set_headers 'Server: MyServer';
}
禁止目录遍历和信息泄露
# 禁止目录列表
autoindex off;
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问敏感文件
location ~* \.(env|git|svn|htaccess|htpasswd|ini|log|sh|conf|bak)$ {
deny all;
}
# 禁止访问备份文件
location ~ ~$ {
deny all;
}
访问控制
# IP 黑白名单
location /admin/ {
# 白名单模式
allow 10.0.0.0/8;
allow 192.168.1.100;
deny all;
# 或使用黑名单模式
# deny 10.10.10.0/24;
# allow all;
}
# HTTP Basic 认证
location /admin/ {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# 同时限制 IP
allow 192.168.1.0/24;
deny all;
satisfy all; # 必须同时满足 IP 和认证
}
# 生成密码文件
# htpasswd -c /etc/nginx/.htpasswd admin
安全头配置
# 全局安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;
8.2 防御常见攻击
防御 CC 攻击
# 组合多种限流策略
http {
# 正常请求限流
limit_req_zone $binary_remote_addr zone=normal:10m rate=30r/s;
# 特殊路径更严格
limit_req_zone $binary_remote_addr zone=strict:10m rate=5r/s;
# 连接数限制
limit_conn_zone $binary_remote_addr zone=conn:10m;
# 使用 geo 模块封禁恶意 IP
geo $blocked_ip {
default 0;
# 已知恶意 IP 段
203.0.113.0/24 1;
198.51.100.0/24 1;
}
server {
# 封禁恶意 IP
if ($blocked_ip) {
return 403;
}
# 连接数限制
limit_conn conn 50;
# 正常请求限流
limit_req zone=normal burst=50 nodelay;
# 敏感路径更严格
location ~* (login|register|search|api) {
limit_req zone=strict burst=10 nodelay;
}
# 检测异常 User-Agent
if ($http_user_agent ~* (nikto|sqlmap|nmap|masscan|dirbuster)) {
return 403;
}
}
}
防御 SQL 注入和 XSS
# 在 server 或 location 块中
# 检测 URL 中的 SQL 注入模式
if ($query_string ~* "(union.*select|insert.*into|delete.*from|drop.*table|update.*set|benchmark\(|sleep\()" ) {
return 403;
}
# 检测常见的 XSS 攻击
if ($query_string ~* "(<|%3C).*script.*(>|%3E)") {
return 403;
}
# 更安全的做法:使用 WAF(如 ModSecurity)
# 或使用 Nginx 的 njs 模块进行请求过滤
防御慢速攻击(Slowloris)
# 设置超时时间
client_header_timeout 10s;
client_body_timeout 10s;
send_timeout 10s;
# 限制请求头大小
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
# 限制请求体大小
client_max_body_size 10m;
# 连接限制
keepalive_timeout 15s;
keepalive_requests 100;
九、模块系统
9.1 模块架构与分类
模块分类
Nginx 的功能通过模块化实现,主要分为以下几类:
核心模块(Core)
提供基础功能,如事件处理、进程管理、配置解析。
events
http
stream
事件模块(Event)
实现不同的 I/O 多路复用机制。
epoll
kqueue
select
poll
HTTP 模块
处理 HTTP 协议相关的各种功能。
proxy
gzip
ssl
rewrite
第三方模块
社区开发的扩展模块,需要编译时加入。
headers-more
echo
lua
njs
模块加载方式
# 动态加载模块
load_module modules/ngx_http_image_filter_module.so;
load_module modules/ngx_http_geoip_module.so;
load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;
9.2 常用第三方模块
Nginx 官方动态模块
| 模块名 | 功能 |
|---|---|
| ngx_http_geoip_module | 基于 GeoIP 数据库的地理位置识别 |
| ngx_http_image_filter_module | 图片实时处理(缩放、裁剪、旋转) |
| ngx_http_xslt_module | XML/XSLT 转换 |
| ngx_stream_module | TCP/UDP 四层代理 |
| ngx_http_perl_module | 嵌入 Perl 脚本 |
社区第三方模块
| 模块名 | 功能 | 安装方式 |
|---|---|---|
| headers-more-nginx-module | 修改/添加/删除响应头 | 编译时 --add-module |
| echo-nginx-module | echo、sleep 等调试指令 | 编译时 --add-module |
| lua-nginx-module (OpenResty) | 嵌入 Lua 脚本,实现复杂逻辑 | OpenResty 或编译 |
| njs | 嵌入 JavaScript 脚本 | 动态加载 |
| ModSecurity | Web 应用防火墙(WAF) | 动态加载 |
| brotli | Brotli 压缩支持 | 编译时 --add-module |
| pagespeed | 自动优化网页性能 | 编译时 --add-module |
十、高级应用场景
10.1 TCP/UDP 四层代理(Stream 模块)
TCP 反向代理
# 在 nginx.conf 顶层配置(与 http 同级)
stream {
# 日志格式
log_format stream_fmt '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr"';
access_log /var/log/nginx/stream.log stream_fmt;
# MySQL 代理
upstream mysql_backend {
server 10.0.0.1:3306;
server 10.0.0.2:3306 backup;
}
server {
listen 3306;
proxy_pass mysql_backend;
proxy_connect_timeout 5s;
proxy_timeout 300s;
}
# Redis 代理
upstream redis_backend {
hash $remote_addr consistent;
server 10.0.0.10:6379;
server 10.0.0.11:6379;
server 10.0.0.12:6379;
}
server {
listen 6379;
proxy_pass redis_backend;
}
# SSH 代理
server {
listen 2222;
proxy_pass 10.0.0.5:22;
proxy_timeout 1h;
}
}
UDP 代理
stream {
# DNS 负载均衡
upstream dns_servers {
server 8.8.8.8:53;
server 8.8.4.4:53;
server 1.1.1.1:53;
}
server {
listen 53 udp;
proxy_pass dns_servers;
proxy_responses 1; # 期望的响应包数
proxy_timeout 5s;
}
}
SNI 路由(基于 TLS SNI 的流量分发)
stream {
# 基于 SNI 将流量分发到不同的后端
map $ssl_preread_server_name $backend {
example.com example_backend;
api.example.com api_backend;
default default_backend;
}
upstream example_backend {
server 10.0.0.1:443;
}
upstream api_backend {
server 10.0.0.2:443;
}
upstream default_backend {
server 10.0.0.3:443;
}
server {
listen 443;
ssl_preread on; # 预读 TLS 握手获取 SNI
proxy_pass $backend;
}
}
10.2 微服务网关配置
API 网关模式
# 各微服务的 upstream
upstream user_service {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
upstream order_service {
server 10.0.2.10:8080;
server 10.0.2.11:8080;
}
upstream product_service {
server 10.0.3.10:8080;
server 10.0.3.11:8080;
}
upstream auth_service {
server 10.0.4.10:8080;
}
# 公共代理配置
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-ID $request_id;
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 限流
limit_req zone=api_global burst=100 nodelay;
# 用户服务
location /api/users {
proxy_pass http://user_service;
limit_req zone=api_strict burst=20 nodelay;
}
# 订单服务
location /api/orders {
proxy_pass http://order_service;
limit_req zone=api_strict burst=20 nodelay;
}
# 商品服务
location /api/products {
proxy_pass http://product_service;
}
# 认证服务
location /api/auth {
proxy_pass http://auth_service;
limit_req zone=login_limit burst=5 nodelay;
}
# 健康检查端点
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
A/B 测试配置
# 使用 split_clients 模块实现流量分割
split_clients "${remote_addr}" $ab_version {
50% "version_a";
* "version_b";
}
upstream app_a {
server 10.0.0.1:8080;
}
upstream app_b {
server 10.0.0.2:8080;
}
server {
listen 80;
server_name app.example.com;
location / {
if ($ab_version = "version_a") {
proxy_pass http://app_a;
}
if ($ab_version = "version_b") {
proxy_pass http://app_b;
}
# 添加标记头用于日志分析
add_header X-AB-Version $ab_version;
}
}
10.3 高可用与蓝绿部署
蓝绿部署
# 定义蓝色和绿色环境
upstream app_blue {
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
upstream app_green {
server 10.0.0.3:8080;
server 10.0.0.4:8080;
}
# 使用 map 或 geo 控制流量方向
map $cookie_deploy_version $backend {
default "app_blue";
"green" "app_green";
}
# 或者通过请求头控制(便于测试)
server {
listen 80;
location / {
# 检查请求头
if ($http_x_deploy_version = "green") {
proxy_pass http://app_green;
break;
}
# 默认使用蓝色环境
proxy_pass http://app_blue;
}
}
# 切换流量:修改 map 中的 default 值,然后 reload
# map $cookie_deploy_version $backend {
# default "app_green"; ← 改为绿色
# "blue" "app_blue";
# }
金丝雀发布(Canary Release)
# 将小比例流量导入新版本
split_clients "${request_id}" $canary {
5% "canary"; # 5% 流量到新版本
* "stable"; # 95% 流量到稳定版
}
upstream stable_backend {
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
upstream canary_backend {
server 10.0.0.3:8080; # 新版本
}
server {
listen 80;
location / {
if ($canary = "canary") {
proxy_pass http://canary_backend;
break;
}
proxy_pass http://stable_backend;
}
}
10.4 Nginx 与 Docker/Kubernetes 集成
Kubernetes Ingress Controller
# Kubernetes Ingress 资源示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/rate-limit: "10"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
Docker 动态配置(模板化)
# 使用 envsubst 动态生成配置
# nginx.template
server {
listen ${LISTEN_PORT:-80};
server_name ${SERVER_NAME:-localhost};
location / {
proxy_pass http://${BACKEND_HOST:-backend}:${BACKEND_PORT:-8080};
}
}
# Dockerfile
FROM nginx:alpine
COPY nginx.template /etc/nginx/templates/default.conf.template
ENV LISTEN_PORT=80
ENV SERVER_NAME=example.com
ENV BACKEND_HOST=backend
ENV BACKEND_PORT=8080
# docker-compose.yml 中使用
# environment:
# - SERVER_NAME=example.com
# - BACKEND_HOST=app
# - BACKEND_PORT=3000
十一、故障排查
11.1 常用诊断命令
基本检查
# 测试配置文件语法
nginx -t
nginx -T # 测试并输出完整配置
# 查看 Nginx 进程
ps aux | grep nginx
# 查看端口占用
ss -tlnp | grep nginx
# 或
netstat -tlnp | grep nginx
# 查看 Nginx 编译参数
nginx -V
# 查看连接状态
ss -s
# 查看当前连接数
ss -tn state established | wc -l
# 查看各状态连接数
ss -tn | awk '{print $1}' | sort | uniq -c | sort -rn
日志分析
# 实时查看访问日志
tail -f /var/log/nginx/access.log
# 实时查看错误日志
tail -f /var/log/nginx/error.log
# 分析访问最多的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 分析访问最多的 URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 分析 HTTP 状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 分析请求方法分布
awk '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 查看带宽使用
awk '{sum+=$10} END {print sum/1024/1024 " MB"}' /var/log/nginx/access.log
性能诊断
# 查看 worker 进程资源使用
top -p $(pgrep -d, nginx)
# 查看文件描述符使用
ls -la /proc/$(pgrep -o nginx)/fd | wc -l
# 使用 strace 跟踪系统调用
strace -p -c
# 使用 perf 分析性能瓶颈
perf record -g -p
perf report
11.2 常见错误及解决方案
错误代码速查表
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 502 Bad Gateway | 后端服务不可用或响应超时 | 检查后端服务状态、端口、防火墙 |
| 504 Gateway Timeout | 后端响应超时 | 增大 proxy_read_timeout,优化后端性能 |
| 413 Request Entity Too Large | 请求体超过限制 | 增大 client_max_body_size |
| 403 Forbidden | 权限不足或被 deny 规则拦截 | 检查文件权限、allow/deny 规则 |
| 429 Too Many Requests | 触发限流 | 调整 limit_req/limit_conn 配置 |
常见问题排查
问题:Worker 进程异常退出
# 检查错误日志
tail -100 /var/log/nginx/error.log
# 检查系统日志
journalctl -u nginx --since "1 hour ago"
dmesg | grep -i oom # 检查 OOM Killer
问题:worker_connections are not enough
# 增加 worker_connections
events {
worker_connections 8192;
}
# 同时确保系统文件描述符足够
worker_rlimit_nofile 16384;
问题:upstream timed out
# 增加超时时间
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 检查后端服务是否健康
curl -I http://backend_server:port/health
问题:SSL 证书错误
# 检查证书有效期
openssl x509 -in /etc/nginx/ssl/cert.pem -noout -dates
# 检查证书链完整性
openssl verify -CAfile /etc/nginx/ssl/chain.pem /etc/nginx/ssl/cert.pem
# 测试 SSL 配置
openssl s_client -connect example.com:443 -servername example.com
11.3 监控与告警
启用 Stub Status 模块
server {
listen 8080;
server_name localhost;
location /nginx_status {
stub_status on;
access_log off;
# 限制访问
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
}
# 输出示例:
# Active connections: 291
# server accepts handled requests
# 16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106
Prometheus 监控(使用 nginx-prometheus-exporter)
# Docker 运行 exporter
docker run -p 9113:9113 \
nginx/nginx-prometheus-exporter:latest \
--nginx.scrape-uri=http://nginx:8080/nginx_status
# 或使用 Nginx Plus 原生支持 Prometheus
# location /api/ {
# api write=on; # Nginx Plus API
# }
关键监控指标
十二、最佳实践
12.1 配置文件组织规范
推荐目录结构
/etc/nginx/
├── nginx.conf # 主配置文件
├── mime.types # MIME 类型映射
├── conf.d/ # 通用配置片段
│ ├── gzip.conf
│ ├── security.conf
│ └── logging.conf
├── sites-available/ # 所有站点配置(激活/未激活)
│ ├── example.com.conf
│ ├── api.example.com.conf
│ └── admin.example.com.conf
├── sites-enabled/ # 已激活的站点(软链接)
│ ├── example.com.conf -> ../sites-available/example.com.conf
│ └── api.example.com.conf -> ../sites-available/api.example.com.conf
├── upstreams/ # upstream 定义
│ ├── backend.conf
│ └── websocket.conf
├── ssl/ # SSL 证书和密钥
│ ├── example.com.crt
│ ├── example.com.key
│ └── dhparam.pem
├── snippets/ # 可复用的配置片段
│ ├── ssl-params.conf
│ └── proxy-params.conf
└── maps/ # map 定义
└── geo-blocking.conf
配置片段复用
# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# /etc/nginx/snippets/proxy-params.conf
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# 在站点配置中引用
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
include snippets/ssl-params.conf;
location / {
proxy_pass http://backend;
include snippets/proxy-params.conf;
}
}
12.2 运维自动化
平滑重载配置
# 测试配置后重载(推荐)
sudo nginx -t && sudo nginx -s reload
# 或
sudo systemctl reload nginx
零停机升级(Hot Upgrade)
#!/bin/bash
# Nginx 零停机升级脚本
OLD_PID=$(cat /run/nginx.pid)
# 1. 用新的二进制文件启动新的 master 进程
kill -USR2 $OLD_PID
# 2. 等待新的 master 进程创建 PID 文件
sleep 1
NEW_PID=$(cat /run/nginx.pid)
# 3. 让旧 master 进程优雅退出 worker
kill -WINCH $OLD_PID
# 4. 确认新进程工作正常后,让旧 master 退出
# kill -QUIT $OLD_PID
# 如果需要回滚:
# kill -HUP $OLD_PID # 重新启动旧 worker
# kill -QUIT $NEW_PID # 关闭新 master
自动化备份与部署脚本
#!/bin/bash
# Nginx 配置部署脚本
NGINX_DIR="/etc/nginx"
BACKUP_DIR="/backup/nginx"
DATE=$(date +%Y%m%d_%H%M%S)
# 创建备份
mkdir -p $BACKUP_DIR
cp -r $NGINX_DIR $BACKUP_DIR/nginx_backup_$DATE
# 同步新配置(从 Git 仓库)
cd /path/to/nginx-config-repo
git pull origin main
# 复制配置到 Nginx 目录
cp -r ./nginx/* $NGINX_DIR/
# 测试配置
if nginx -t 2>&1 | grep -q "syntax is ok"; then
echo "配置测试通过,正在重载..."
nginx -s reload
echo "部署成功!"
else
echo "配置测试失败,正在回滚..."
rm -rf $NGINX_DIR
cp -r $BACKUP_DIR/nginx_backup_$DATE $NGINX_DIR
echo "已回滚到上一版本"
exit 1
fi
Ansible 自动化管理
---
# Ansible Playbook: nginx-deploy.yml
- hosts: webservers
become: yes
tasks:
- name: Copy nginx configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: 'nginx -t -c %s'
notify: reload nginx
- name: Copy site configurations
template:
src: "sites/{{ item }}.conf.j2"
dest: "/etc/nginx/sites-available/{{ item }}.conf"
loop: "{{ nginx_sites }}"
notify: reload nginx
- name: Enable sites
file:
src: "/etc/nginx/sites-available/{{ item }}.conf"
dest: "/etc/nginx/sites-enabled/{{ item }}.conf"
state: link
loop: "{{ nginx_enabled_sites }}"
notify: reload nginx
handlers:
- name: reload nginx
service:
name: nginx
state: reloaded
12.3 完整生产环境配置模板
生产环境完整 nginx.conf
# ===== 全局配置 =====
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
worker_cpu_affinity auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
# ===== 事件配置 =====
events {
worker_connections 4096;
use epoll;
multi_accept on;
accept_mutex off;
}
# ===== HTTP 配置 =====
http {
# --- 基本设置 ---
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
client_max_body_size 50m;
types_hash_max_size 2048;
server_names_hash_bucket_size 128;
# --- 日志配置 ---
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" '
'rt=$request_time';
access_log /var/log/nginx/access.log main buffer=16k flush=5s;
# --- 压缩配置 ---
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types text/plain text/css application/json
application/javascript text/xml
application/xml application/xml+rss
text/javascript image/svg+xml;
# --- 限流配置 ---
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# --- 文件缓存 ---
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# --- 代理缓存路径 ---
proxy_cache_path /var/cache/nginx/proxy levels=1:2
keys_zone=static_cache:10m max_size=10g inactive=1d
use_temp_path=off;
# --- 上游服务器定义 ---
include /etc/nginx/upstreams/*.conf;
# --- 站点配置 ---
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}
生产站点配置示例
# /etc/nginx/sites-available/example.com.conf
# HTTP -> HTTPS 重定向
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 主站
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# SSL 配置
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
include snippets/ssl-params.conf;
# 根目录
root /var/www/example.com/html;
index index.html;
# 安全头
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 限流
limit_req zone=general burst=50 nodelay;
limit_conn conn_limit 100;
# 静态文件
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff2?|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# HTML 文件
location ~* \.html?$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# API 代理
location /api/ {
limit_req zone=api burst=30 nodelay;
proxy_pass http://api_backend;
include snippets/proxy-params.conf;
}
# 默认路由
location / {
try_files $uri $uri/ /index.html;
}
# 健康检查
location = /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
# www 重定向到非 www
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
return 301 https://example.com$request_uri;
}
12.4 Nginx 与主流技术栈集成
Nginx + Node.js
upstream nodejs_app {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 80;
server_name nodeapp.example.com;
location / {
proxy_pass http://nodejs_app;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket 支持
location /socket.io/ {
proxy_pass http://nodejs_app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Nginx + Python (Gunicorn/uWSGI)
# Gunicorn
upstream gunicorn_app {
server unix:/run/gunicorn.sock;
# 或: server 127.0.0.1:8000;
}
server {
listen 80;
server_name python-app.example.com;
location / {
proxy_pass http://gunicorn_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Django 静态文件
location /static/ {
alias /var/www/python-app/static/;
expires 30d;
}
}
# uWSGI
server {
listen 80;
server_name uwsgi-app.example.com;
location / {
uwsgi_pass unix:///run/uwsgi.sock;
# 或: uwsgi_pass 127.0.0.1:3031;
include uwsgi_params;
uwsgi_param Host $host;
uwsgi_param X-Real-IP $remote_addr;
}
}
Nginx + PHP (PHP-FPM)
server {
listen 80;
server_name php-app.example.com;
root /var/www/php-app/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
# 或: fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 性能优化
fastcgi_buffer_size 32k;
fastcgi_buffers 16 16k;
fastcgi_busy_buffers_size 32k;
}
# Laravel 特定
location ~ /\.(?!well-known).* {
deny all;
}
}
45.64.74.193