Nginx 是一个高性能的 HTTP 和反向代理服务器。它以其高性能、稳定性、丰富的功能集、简单的配置和低资源消耗而闻名。本文介绍如何配置 Nginx 。
主要特点
- 高性能: 采用事件驱动架构,能够处理大量并发连接
- 低资源消耗: 内存占用少
- 反向代理: 支持 HTTP、HTTPS、TCP 和 UDP 协议
- 负载均衡: 支持多种负载均衡算法
- 静态文件服务: 高效处理静态资源
- 热部署: 支持不停机更新配置
Nginx 进程模型
Master-Worker 架构
Nginx 采用多进程模型,包含一个 Master 进程和多个 Worker 进程:
┌─────────────────────────────────────┐
│ Master 进程 (主控进程) │
│ - 读取配置文件 │
│ - 管理 Worker 进程 │
│ - 处理信号(reload/stop) │
└──────────┬──────────────────────────┘
│
┌──────┴──────┬──────┬──────┐
↓ ↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐
│Worker 1│ │Worker 2│ │Worker N│
│ │ │ │ │ │
│处理请求│ │处理请求│ │处理请求│
└────────┘ └────────┘ └────────┘
1. Master 进程(主进程)
职责:
- 读取和验证配置文件
- 创建、管理和监控 Worker 进程
- 接收外部信号(如 reload、stop、quit)
- 不处理实际的网络请求
特点:
- 以 root 权限运行(需要绑定 80/443 端口)
- 在整个生命周期中只有一个
2. Worker 进程(工作进程)
职责:
- 实际处理客户端请求
- 接收来自 Master 分配的连接
- 执行反向代理、负载均衡等操作
- 处理静态文件、动态内容
特点:
- 以普通用户权限运行(由
user指令指定) - 数量由
worker_processes指令配置 - 每个 Worker 独立运行,互不影响
- 采用异步非阻塞的事件驱动模型
关键配置参数
worker_processes(Worker 进程数)
# 全局块配置
worker_processes auto; # 自动检测 CPU 核心数
# worker_processes 4; # 手动指定为 4 个 Worker
配置建议:
- 推荐值:
auto或等于 CPU 核心数 - 原因:每个 Worker 绑定一个 CPU 核心,避免进程切换开销
- 查看 CPU 核心数:
grep processor /proc/cpuinfo | wc -l(Linux) 或sysctl -n hw.ncpu(macOS)
示例:
- 4 核 CPU →
worker_processes 4; - 8 核 CPU →
worker_processes 8;
worker_connections(每个 Worker 的最大连接数)
events {
worker_connections 1024; # 每个 Worker 最多处理 1024 个连接
}
含义:
- 单个 Worker 进程能同时处理的最大连接数
- 包括与客户端的连接和与后端服务器的连接
计算公式:
理论最大并发连接数 = worker_processes × worker_connections
作为反向代理时的并发数 = (worker_processes × worker_connections) / 2
# 除以 2 是因为每个客户端请求需要 2 个连接:
# 1 个连接到 Nginx,1 个 Nginx 到后端服务器
完整示例与计算
# 4 核 CPU 服务器,预期支持 8000 并发连接
user nginx;
worker_processes 4; # 4 个 Worker(匹配 CPU 核心数)
worker_rlimit_nofile 65535; # 每个 Worker 最多打开 65535 个文件
events {
worker_connections 4096; # 每个 Worker 处理 4096 个连接
use epoll; # Linux 使用 epoll(高性能)
multi_accept on; # 一次接受多个连接
}
# 计算结果:
# - 最大并发连接数 = 4 × 4096 = 16384(作为 Web 服务器)
# - 作为反向代理 = 16384 / 2 = 8192(满足 8000 并发需求)
基本配置结构
Nginx 配置文件采用块级结构(Block-based),由一系列指令(directives)和块(blocks)组成。配置文件通常位于 /etc/nginx/nginx.conf。
1. 配置块(Context)
Nginx 配置由多个层级的配置块组成,每个块定义了一个配置上下文:
全局块(main)
├── events 块 # 事件模型配置
└── http 块 # HTTP 相关配置
├── upstream 块 # 负载均衡配置
├── server 块 # 虚拟主机配置
│ └── location 块 # 请求路由配置
└── server 块
└── location 块
2. 各配置块的作用
| 配置块 | 作用域 | 主要配置内容 |
|---|---|---|
| main(全局块) | 整个 Nginx | worker 进程数、用户权限、错误日志、PID 文件 |
| events | 所有网络连接 | 连接数限制、事件驱动模型(epoll/kqueue) |
| http | 所有 HTTP 请求 | MIME 类型、日志格式、Gzip、超时时间 |
| upstream | 后端服务器组 | 负载均衡算法、服务器列表、健康检查 |
| server | 单个虚拟主机 | 监听端口、域名、SSL 证书 |
| location | 特定 URL 路径 | 代理规则、静态文件路径、重写规则 |
3. 指令继承与覆盖
- 子块继承父块:子块会继承父块的配置
- 子块可覆盖父块:子块中的相同指令会覆盖父块的配置
http {
# 所有 server 都会继承这个配置
client_max_body_size 10m;
server {
# 这个 server 覆盖了父块的配置
client_max_body_size 50m;
location /upload {
# 这个 location 又覆盖了 server 的配置
client_max_body_size 100m;
}
}
}
核心配置指令详解
1. 基础配置指令
监听与域名
上下文:server
server {
listen 80; # 监听端口
listen 443 ssl http2; # 监听 HTTPS 端口并启用 HTTP/2
server_name example.com; # 服务器域名
}
| 指令 | 作用 | 适用上下文 | 示例 |
|---|---|---|---|
| listen | 指定监听的端口和协议 | server | listen 80;listen 443 ssl; |
| server_name | 匹配请求的域名 | server | server_name example.com www.example.com; |
listen 参数说明:
80:HTTP 默认端口443 ssl:HTTPS 端口,启用 SSLhttp2:启用 HTTP/2 协议(需要 SSL)default_server:默认虚拟主机,匹配不到其他 server 时使用
文件路径
上下文:http, server, location
http {
root /var/www; # HTTP 块设置默认根目录
server {
root /var/www/html; # server 块可覆盖
index index.html index.htm;
location /app/ {
root /data; # location 块可再次覆盖
# 或使用 alias
alias /data/app/;
}
}
}
| 指令 | 作用 | 适用上下文 | 示例 |
|---|---|---|---|
| root | 设置资源根目录 | http, server, location | root /var/www/html; |
| index | 目录访问时的默认文件 | http, server, location | index index.html index.htm; |
| alias | 替换路径(仅 location) | location | alias /data/; |
root vs alias:
root:拼接路径(root /var/www;+location /app/→/var/www/app/)alias:替换路径(alias /data/;+location /app/→/data/)
2. Location 路径匹配
上下文:server, location(location 可嵌套)
server {
listen 80;
location / { } # 前缀匹配
location = /exact { } # 精确匹配
location ^~ /static/ { } # 优先前缀匹配
location ~ \.php$ { } # 正则匹配(区分大小写)
location ~* \.(jpg|png)$ { } # 正则匹配(不区分大小写)
# location 可以嵌套
location /api/ {
location /api/admin/ {
# 嵌套 location
}
}
}
| 修饰符 | 匹配方式 | 优先级 | 适用上下文 | 示例 |
|---|---|---|---|---|
= | 精确匹配 | 最高 | server, location | location = / { } |
^~ | 前缀匹配(不检查正则) | 高 | server, location | location ^~ /static/ { } |
~ | 正则匹配(区分大小写) | 中 | server, location | location ~ \.php$ { } |
~* | 正则匹配(不区分大小写) | 中 | server, location | location ~* \.(jpg|png)$ { } |
| 无 | 普通前缀匹配 | 低 | server, location | location / { } |
try_files
上下文:server, location
server {
try_files $uri $uri/ /index.html; # server 级别
location / {
try_files $uri $uri/ /index.html; # location 级别
# 依次尝试:1. 文件 2. 目录 3. 返回 index.html
}
}
| 指令 | 作用 | 适用上下文 |
|---|---|---|
| try_files | 按顺序检查文件是否存在 | server, location |
常用场景:SPA 应用的前端路由支持
3. 反向代理指令
所有 proxy_ 指令的上下文*:http, server, location
基础代理
上下文:location(主要),server(少见)
http {
server {
location / {
proxy_pass http://backend; # 代理到后端服务器
}
location /api/ {
proxy_pass http://localhost:3000; # 代理到本地端口
proxy_pass http://backend/api/; # 代理并修改路径
}
}
}
| 指令 | 作用 | 适用上下文 | 示例 |
|---|---|---|---|
| proxy_pass | 转发请求到后端 | location, if in location | proxy_pass http://backend; |
路径处理规则:
proxy_pass http://backend;→ 保留完整 URIproxy_pass http://backend/;→ 替换 location 路径
请求头设置
上下文:http, server, location
http {
# http 块:所有 server 继承
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
server {
# server 块:所有 location 继承
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
# location 块:仅此 location 生效
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
| 指令 | 作用 | 适用上下文 | 常用值 |
|---|---|---|---|
| proxy_set_header | 设置转发到后端的请求头 | http, server, location | Host $host |
常用请求头:
Host:原始请求的域名X-Real-IP:客户端真实 IPX-Forwarded-For:完整的代理链 IPX-Forwarded-Proto:原始协议(http/https)Upgrade+Connection:WebSocket 支持
代理超时
上下文:http, server, location
http {
proxy_connect_timeout 60s; # http 块:默认连接超时
server {
proxy_read_timeout 120s; # server 块:覆盖为 120s
location /api/ {
proxy_connect_timeout 120s; # location 块:长连接接口
proxy_read_timeout 180s; # 长耗时任务
proxy_send_timeout 180s; # 大文件上传
}
}
}
| 指令 | 作用 | 适用上下文 | 默认值 | 适用场景 |
|---|---|---|---|---|
| proxy_connect_timeout | 与后端建立连接的超时 | http, server, location | 60s | 网络慢时增加 |
| proxy_read_timeout | 从后端读取响应的超时 | http, server, location | 60s | 长耗时任务增加 |
| proxy_send_timeout | 向后端发送请求的超时 | http, server, location | 60s | 大文件上传增加 |
错误重试
上下文:http, server, location
http {
# http 块:全局重试策略
proxy_next_upstream error timeout http_502;
proxy_next_upstream_tries 3;
server {
location /api/ {
# location 块:特定接口覆盖
proxy_next_upstream error timeout;
proxy_next_upstream_tries 2;
}
}
}
| 指令 | 作用 | 适用上下文 | 示例 |
|---|---|---|---|
| proxy_next_upstream | 何时尝试下一个服务器 | http, server, location | error timeout http_502 |
| proxy_next_upstream_tries | 最大重试次数 | http, server, location | 3 |
proxy_next_upstream 参数:
error:连接错误timeout:超时http_502/503/504:后端返回特定错误码off:禁用重试
4. SSL/HTTPS 配置
所有 ssl_ 指令的上下文*:http, server(主要在 server 块使用)
证书配置
上下文:http, server
http {
# http 块:所有 HTTPS server 的默认证书
# ssl_certificate /path/to/default.pem;
# ssl_certificate_key /path/to/default.key;
server {
listen 443 ssl http2;
# server 块:为此虚拟主机指定证书
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_dhparam /path/to/dhparam.pem;
}
}
| 指令 | 作用 | 适用上下文 | 必需 |
|---|---|---|---|
| ssl_certificate | SSL 证书文件路径 | http, server | ✅ |
| ssl_certificate_key | SSL 私钥文件路径 | http, server | ✅ |
| ssl_dhparam | DH 参数(增强安全性) | http, server | 推荐 |
会话优化
上下文:http, server
http {
# http 块:所有 HTTPS server 共享会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets on;
}
| 指令 | 作用 | 适用上下文 | 性能影响 |
|---|---|---|---|
| ssl_session_cache | SSL 会话缓存 | http, server | 减少 1-2 RTT |
| ssl_session_timeout | 会话有效期 | http, server | 10m 为佳 |
| ssl_session_tickets | 无状态会话恢复 | http, server | 减少服务器内存 |
5. 缓存控制
上下文:
expires:http,server,locationadd_header:http,server,location
http {
expires 7d; # http 块:默认缓存 7 天
server {
location / {
expires -1; # 首页不缓存
}
location ~* \.(js|css)$ {
expires 1y; # 静态资源缓存 1 年
add_header Cache-Control "public, immutable";
}
}
}
| 指令 | 作用 | 适用上下文 | 示例 |
|---|---|---|---|
| expires | 设置过期时间 | http, server, location | 30d, 1y, -1 |
| add_header | 添加响应头 | http, server, location | Cache-Control "no-store" |
Cache-Control 常用值:
public:允许 CDN 和代理缓存private:仅浏览器缓存no-store:完全不缓存no-cache:每次验证缓存immutable:文件永不改变(适合带哈希的文件)
6. 负载均衡指令
upstream backend {
least_conn; # 负载均衡算法
server backend1.com:8080 weight=3; # 后端服务器 + 权重
server backend2.com:8080 weight=2;
server backend3.com:8080 backup; # 备用服务器
}
upstream 块指令
| 指令 | 作用 | 示例 |
|---|---|---|
| server | 定义后端服务器 | server 192.168.1.10:8080; |
| weight | 服务器权重 | weight=3 |
| backup | 备用服务器标记 | backup |
| max_fails | 失败次数阈值 | max_fails=3 |
| fail_timeout | 失败超时时间 | fail_timeout=30s |
负载均衡算法
| 算法 | 指令 | 特点 |
|---|---|---|
| 轮询 | 默认 | 依次分配 |
| 最少连接 | least_conn; | 分配给连接数最少的服务器 |
| IP 哈希 | ip_hash; | 同一 IP 始终访问同一服务器 |
| 随机 | random; | 随机选择服务器 |
7. Gzip 压缩
上下文:http, server, location
http {
# http 块:全局启用 gzip
gzip on;
gzip_vary on;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_buffers 32 4k;
gzip_types text/plain text/css application/javascript;
gzip_disable "MSIE [1-6]\.";
server {
# server 块可覆盖
gzip_comp_level 9; # 此 server 使用更高压缩级别
}
}
| 指令 | 作用 | 适用上下文 | 推荐值 |
|---|---|---|---|
| gzip | 启用 gzip 压缩 | http, server, location | on |
| gzip_min_length | 最小压缩大小 | http, server, location | 1k |
| gzip_comp_level | 压缩级别 | http, server, location | 6(1-9,越高越慢) |
| gzip_types | 要压缩的文件类型 | http, server, location | text/* application/javascript ... |
| gzip_disable | 禁用 gzip 的条件 | http, server, location | "MSIE [1-6]\." |
8. URL 重写
上下文:
return:server,location,ifrewrite:server,location,if
server {
# server 块:重定向所有 HTTP 到 HTTPS
return 301 https://$server_name$request_uri;
location /old/ {
# location 块:URL 重写
rewrite ^/old(.*)$ /new$1 permanent;
}
}
| 指令 | 作用 | 适用上下文 | 状态码 |
|---|---|---|---|
| return | 立即返回响应 | server, location, if | 301, 302, 200 等 |
| rewrite | URL 重写 | server, location, if | permanent(301), redirect(302) |
rewrite 标志:
permanent:301 永久重定向redirect:302 临时重定向break:停止当前规则,不再匹配last:停止当前规则,重新搜索 location
9. 限流限速
上下文:
limit_req_zone:httplimit_req:http,server,location
http {
# http 块:定义限流区域(必须在 http 块)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api/ {
# location 块:应用限流
limit_req zone=api_limit burst=20 nodelay;
}
}
}
| 指令 | 作用 | 适用上下文 | 示例 |
|---|---|---|---|
| limit_req_zone | 定义限流区域 | http | zone=api_limit:10m rate=10r/s |
| limit_req | 应用限流 | http, server, location | zone=api_limit burst=20 |
参数说明:
zone=name:size:共享内存区域名和大小rate=10r/s:每秒 10 个请求burst=20:允许突发 20 个请求nodelay:不延迟处理突发请求
10. 常用变量
Nginx 提供了大量内置变量,用于配置中的动态取值:
| 变量 | 含义 | 示例值 |
|---|---|---|
| $host | 请求的主机名 | example.com |
| $server_name | server 块定义的域名 | example.com |
| $uri | 当前请求的 URI | /path/to/file.html |
| $request_uri | 完整的原始 URI(含参数) | /path?id=123 |
| $scheme | 协议 | http 或 https |
| $remote_addr | 客户端 IP | 192.168.1.100 |
| $proxy_add_x_forwarded_for | 追加 X-Forwarded-For | 客户端IP, 代理IP |
| $http_upgrade | Upgrade 请求头的值 | websocket |
| $http_user_agent | User-Agent 请求头 | Mozilla/5.0 ... |
实战配置案例
1. HTTP 与 HTTPS 共存配置
场景:同时监听 80 和 443 端口,在同一个 server 块中处理。
server {
listen 80;
listen 443 ssl http2;
server_name example.com;
charset utf-8;
# SSL 证书配置
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_dhparam /path/to/dhparam.pem;
# 应用配置...
}
优点:减少配置重复,HTTP 和 HTTPS 共享同一套 location 规则。
2. 微服务路由配置
场景:将不同路径的请求路由到不同的后端微服务。
server {
listen 443 ssl http2;
server_name api.example.com;
# API 服务
location /api/ {
client_max_body_size 100m;
proxy_connect_timeout 120s;
proxy_set_header X-Origin-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host api-service.internal;
proxy_next_upstream off;
proxy_next_upstream_tries 3;
proxy_pass http://api_backend;
}
# 管理后台服务
location /admin/ {
client_max_body_size 200m;
proxy_connect_timeout 180s;
proxy_read_timeout 180s;
proxy_set_header X-Origin-Host $host;
proxy_set_header Host admin-service.internal;
proxy_pass http://admin_backend;
}
}
关键点:
- 不同服务配置不同的超时和请求体大小
- 使用
X-Origin-Host保留原始域名 - 覆盖
Host头用于内部服务路由
3. SPA + OSS 静态资源
场景:前端应用 托管在 OSS,通过 Nginx 代理访问。
server {
listen 443 ssl http2;
server_name app.example.com;
# 主应用(从 OSS 代理)
location / {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN" always;
proxy_intercept_errors on;
error_page 404 =200 /index.html;
proxy_pass https://cdn.example.com/app/web-static/production/;
}
# 特定版本的应用(支持 commit/review 分支预览)
location ~ /(commit|review)/(.*)/app/(.*) {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN" always;
# URL 重写
rewrite ^/(commit|review)/(.*)/app/(.*) /app/web-static/$1/$2/index.html break;
proxy_pass https://cdn.example.com;
}
}
技巧:
error_page 404 =200 /index.html:将 404 转为 200,支持前端路由- 在 location 块内启用 gzip,针对特定路径优化
- 使用正则捕获组实现灵活的 URL 重写
4. WebSocket 长连接支持
场景:支持 WebSocket 实时通信。
location /ws/ {
proxy_pass http://websocket_backend;
# WebSocket 必需配置
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超长超时时间(1 小时)
proxy_read_timeout 3600s;
}
关键点:
- 必须设置
proxy_http_version 1.1 - 必须设置
Upgrade和Connection头 - 设置足够长的
proxy_read_timeout