4450 字
22 分钟
Nginx 反向代理配置实战完全指南:从入门到生产部署 | 2026 最新
Nginx 是目前最流行的 Web 服务器和反向代理工具,全球超过 40% 的网站使用 Nginx。无论是部署 Node.js / Python / Java 应用,还是搭建负载均衡集群,Nginx 反向代理都是必备技能。
本文从零开始,系统讲解 Nginx 反向代理的完整知识体系,包括:
- 反向代理核心原理与基础配置
proxy_pass详细语法与路径匹配规则- 负载均衡(轮询/加权/ip_hash/least_conn)
- HTTPS/SSL 终止配置
- WebSocket 代理配置
- 缓存加速配置
- 安全加固与性能优化
- 常见场景实战(Node.js/Python/Java/静态资源)
- 错误排查与最佳实践
前置阅读:本文假设你已掌握 Linux 基础命令。如需复习,请阅读:Linux 常用命令速查手册
1. 反向代理核心原理
1.1 什么是反向代理?
正向代理 vs 反向代理对比:
=== 正向代理(隐藏客户端)===客户端 → 正向代理 → 互联网 → 目标服务器 ↑ 目标服务器不知道真实客户端 IP
=== 反向代理(隐藏服务器)===客户端 → 反向代理 → 后端服务器 A → 后端服务器 B → 后端服务器 C ↑ 客户端不知道后端服务器的存在反向代理的核心价值:
| 价值 | 说明 |
|---|---|
| 隐藏后端 | 客户端只接触反向代理,后端 IP 不暴露 |
| 负载均衡 | 将请求分发到多台后端服务器 |
| SSL 终止 | 在反向代理层处理 HTTPS,后端只需处理 HTTP |
| 缓存加速 | 反向代理缓存静态资源和 API 响应 |
| 安全过滤 | 在反向代理层做 WAF、限流、防 DDoS |
| 统一入口 | 多个后端服务共用一个域名和端口 |
1.2 Nginx 请求处理流程
客户端请求 ↓Nginx 接收(80/443 端口) ↓server { ... } 匹配域名 ↓location { ... } 匹配路径 ↓proxy_pass 转发到后端 ↓后端处理请求 ↓Nginx 接收后端响应 ↓返回给客户端2. 基础反向代理配置
2.1 最简配置
server { listen 80; server_name example.com;
location / { proxy_pass http://127.0.0.1:3000; # 转发到本地 3000 端口 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_pass | 转发目标地址(HTTP/HTTPS/Unix Socket) |
proxy_set_header | 设置转发给后端的请求头 |
X-Real-IP | 传递客户端真实 IP |
X-Forwarded-For | 传递经过的代理链 IP 列表 |
X-Forwarded-Proto | 传递原始请求协议(http/https) |
2.2 proxy_pass 路径匹配规则(重点!)
proxy_pass 的路径拼接规则容易出错,务必理解:
# === 情况一:proxy_pass 不带 URI(末尾无 /path)===location /api/ { proxy_pass http://127.0.0.1:3000; # 不带 URI # 请求 /api/users → 转发到 http://127.0.0.1:3000/api/users # 完整路径(含 location 匹配部分)会附加到目标地址}
# === 情况二:proxy_pass 带 URI(末尾有 /path)===location /api/ { proxy_pass http://127.0.0.1:3000/v2/; # 带 URI(末尾有 /) # 请求 /api/users → 转发到 http://127.0.0.1:3000/v2/users # location 匹配的部分(/api/)被替换为 proxy_pass 中的 URI(/v2/)}
# === 情况三:正则表达式 location ===location ~ ^/api/(.*)$ { proxy_pass http://127.0.0.1:3000/$1; # 必须用变量形式 # 正则 location 中,proxy_pass 不能带普通 URI,必须用变量}记忆口诀:
proxy_pass不带 URI → 保留原始请求路径proxy_pass带 URI → 用 URI 替换 location 匹配部分- 正则 location →
proxy_pass必须用变量(如$1)
2.3 常用 proxy_set_header 配置
location / { proxy_pass http://127.0.0.1:3000;
# 基础头(必须配置) 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 支持(见第 6 节详解) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
# 超时配置(生产环境必须调整) proxy_connect_timeout 5s; # 连接后端超时 proxy_send_timeout 30s; # 发送请求到后端超时 proxy_read_timeout 30s; # 读取后端响应超时
# 缓冲配置 proxy_buffering on; proxy_buffer_size 8k; proxy_buffers 8 8k;}3. 负载均衡配置
3.1 upstream 基础配置
# 定义后端服务器组upstream backend { server 127.0.0.1:3001; server 127.0.0.1:3002; server 127.0.0.1:3003;}
server { listen 80; server_name example.com;
location / { proxy_pass http://backend; # 使用 upstream 名称 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }}3.2 负载均衡策略详解
upstream backend { # === 策略一:轮询(默认)=== # 依次将请求分发给每个后端,适合后端性能相近的场景 server 127.0.0.1:3001; server 127.0.0.1:3002; server 127.0.0.1:3003;}
upstream backend_weighted { # === 策略二:加权轮询 === # weight 越高,分配到的请求越多,适合后端性能不均 server 127.0.0.1:3001 weight=3; # 60% 请求 server 127.0.0.1:3002 weight=2; # 40% 请求 server 127.0.0.1:3003 weight=1; # 20% 请求}
upstream backend_iphash { # === 策略三:ip_hash === # 按客户端 IP 哈希分配,保证同一客户端总是访问同一后端 # 适合有状态应用(如未使用共享 Session 的场景) ip_hash; server 127.0.0.1:3001; server 127.0.0.1:3002; server 127.0.0.1:3003;}
upstream backend_leastconn { # === 策略四:least_conn === # 优先将请求分发到活跃连接数最少的后端(动态负载均衡) # 适合请求处理时间差异较大的场景 least_conn; server 127.0.0.1:3001; server 127.0.0.1:3002; server 127.0.0.1:3003;}3.3 后端服务器状态控制
upstream backend { server 127.0.0.1:3001 weight=5 max_fails=3 fail_timeout=30s; server 127.0.0.1:3002 weight=3 max_fails=3 fail_timeout=30s; server 127.0.0.1:3003 weight=2 max_fails=3 fail_timeout=30s; server 127.0.0.1:3004 backup; # 备份服务器(其他都宕机时才启用) server 127.0.0.1:3005 down; # 标记下线(维护时临时移除)}参数说明:
| 参数 | 说明 |
|---|---|
weight | 权重,越高分配请求越多 |
max_fails | 在 fail_timeout 时间内,最多允许失败次数 |
fail_timeout | 失败超时时间,超过 max_fails 次后,该后端被标记为不可用的时间 |
backup | 备份服务器,其他服务器都不可用时才启用 |
down | 永久标记为不可用 |
3.4 健康检查(高级)
Nginx 开源版只支持被动健康检查(失败后标记不可用)。主动健康检查需要 Nginx Plus 或用 njs 模块实现,也可用第三方模块 nginx_upstream_check_module。
# 被动健康检查(开源版自带)upstream backend { server 127.0.0.1:3001 max_fails=2 fail_timeout=10s; server 127.0.0.1:3002 max_fails=2 fail_timeout=10s; # 10 秒内失败 2 次,则该后端被标记为不可用 10 秒}4. HTTPS/SSL 终止配置
4.1 基础 HTTPS 反向代理
# HTTP 自动跳转 HTTPSserver { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri;}
# HTTPS 反向代理server { listen 443 ssl http2; server_name example.com www.example.com;
# SSL 证书配置 ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL 安全配置(推荐) ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
# HSTS(强制 HTTPS) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / { proxy_pass http://127.0.0.1:3000; 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; }}4.2 Let’s Encrypt 自动证书(推荐)
# 安装 certbotapt install certbot python3-certbot-nginx # Debian/Ubuntuyum install certbot python3-certbot-nginx # CentOS/RHEL
# 自动配置 Nginx(交互式)certbot --nginx -d example.com -d www.example.com
# 自动续期(certbot 会自动配置 cron)certbot renew --dry-run # 测试自动续期certbot 会自动修改 Nginx 配置,添加 SSL 证书路径和 HTTPS 配置。
4.3 SSL 终止 + 负载均衡(生产标准配置)
# 定义后端(内网 HTTP,不走 HTTPS)upstream backend { server 10.0.0.101:8080 weight=3; server 10.0.0.102:8080 weight=2; server 10.0.0.103:8080 weight=1 backup;}
# HTTP 跳转 HTTPSserver { listen 80; server_name api.example.com; return 301 https://$host$request_uri;}
# HTTPS 入口(SSL 终止在这里做)server { listen 443 ssl http2; server_name api.example.com;
# Let's Encrypt 证书 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;
# 安全头 add_header Strict-Transport-Security "max-age=31536000" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always;
# API 代理 location / { proxy_pass http://backend; 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;
# API 场景超时时间要长一些 proxy_connect_timeout 5s; proxy_read_timeout 60s; proxy_send_timeout 60s; }
# 健康检查端点(负载均衡场景) location /health { access_log off; return 200 "OK\n"; add_header Content-Type "text/plain"; }}5. 缓存配置加速
5.1 基础代理缓存
# 定义缓存区(在 http 块中配置)http { # 缓存区:名称=one,缓存路径=/var/cache/nginx,最大 10m 索引,缓存 1g 磁盘空间 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:10m max_size=1g inactive=60m use_temp_path=off;
server { listen 80; server_name example.com;
location / { proxy_pass http://127.0.0.1:3000;
# 启用缓存 proxy_cache one; proxy_cache_key $scheme$request_method$host$request_uri; proxy_cache_valid 200 302 10m; # 200/302 缓存 10 分钟 proxy_cache_valid 404 1m; # 404 缓存 1 分钟 proxy_cache_valid any 5m; # 其他状态码缓存 5 分钟
# 缓存命中状态(响应头中可以看到) add_header X-Cache-Status $upstream_cache_status;
# 跳过缓存的条件 proxy_cache_bypass $http_cache_control; # 带 Cache-Control: no-cache 则不缓存 } }}5.2 缓存状态说明
响应头 X-Cache-Status 的可能值:
| 值 | 说明 |
|---|---|
HIT | 缓存命中,直接返回缓存内容 |
MISS | 缓存未命中,请求转发到后端 |
EXPIRED | 缓存已过期,重新请求后端 |
STALE | 缓存过期但后端不可用,返回过期缓存 |
BYPASS | 因 proxy_cache_bypass 跳过缓存 |
UPDATING | 缓存更新中,返回旧缓存 |
5.3 按路径精细化缓存
server { listen 80; server_name example.com;
# 静态资源:长缓存 location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?)$ { proxy_pass http://127.0.0.1:3000; proxy_cache one; proxy_cache_valid 200 7d; # 静态资源缓存 7 天 proxy_cache_valid any 1m; add_header X-Cache-Status $upstream_cache_status; expires 7d; # 浏览器缓存 7 天 add_header Cache-Control "public, max-age=604800"; }
# API 接口:短缓存或不缓存 location /api/ { proxy_pass http://127.0.0.1:3000; proxy_cache one; proxy_cache_valid 200 1m; # API 缓存 1 分钟 proxy_cache_valid any 0s; # 其他不缓存 proxy_no_cache $http_authorization; # 有 Authorization 头时不缓存 }
# 动态页面:不缓存 location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 不启用缓存 }}6. WebSocket 代理配置
6.1 完整 WebSocket 配置
map $http_upgrade $connection_upgrade { default upgrade; '' close;}
server { listen 80; server_name ws.example.com;
location /ws/ { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1;
# WebSocket 核心配置 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
# 延长超时(WebSocket 是长连接) proxy_read_timeout 3600s; proxy_send_timeout 3600s;
# 传递真实 IP proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}6.2 map 指令说明
map 指令用于根据变量值动态设置另一个变量:
# 在 http 块中(不能在 server 或 location 中)http { map $http_upgrade $connection_upgrade { default upgrade; # 默认:Upgrade(WebSocket 握手) '' close; # 如果没有 Upgrade 头:close } # ...}这样配置后,普通 HTTP 请求($http_upgrade 为空)走普通连接,WebSocket 请求($http_upgrade = websocket)走 Upgrade 连接。
6.3 Socket.IO 专用配置
server { listen 80; server_name socket.example.com;
location /socket.io/ { proxy_pass http://127.0.0.1:3000/socket.io/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Socket.IO 特殊配置 proxy_read_timeout 86400s; # 24 小时(长轮询兼容) }}7. 常见场景实战配置
7.1 Node.js 应用反向代理
upstream nodeapp { server 127.0.0.1:3000; server 127.0.0.1:3001; server 127.0.0.1:3002;}
server { listen 80; server_name myapp.com;
# 压缩(减少传输大小) gzip on; gzip_types text/plain text/css application/json application/javascript;
# 静态资源直接由 Nginx 提供(不经过 Node.js) location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { root /var/www/myapp/public; expires 30d; access_log off; }
# Node.js 动态请求 location / { proxy_pass http://nodeapp; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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_read_timeout 300s; }}7.2 Python(Gunicorn/uWSGI)反向代理
upstream django { # Unix Socket(性能比 TCP 好) server unix:/run/gunicorn.sock fail_timeout=0; # 或者用 TCP # server 127.0.0.1:8000;}
server { listen 80; server_name django.example.com;
# 上传文件大小限制 client_max_body_size 100M;
# 静态文件(Django 设置 STATIC_ROOT 后 collectstatic 收集到这里) location /static/ { alias /var/www/django/static/; expires 30d; access_log off; }
# 媒体文件(用户上传) location /media/ { alias /var/www/django/media/; expires 7d; access_log off; }
# Django 应用 location / { proxy_pass http://django; 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; }}7.3 Java(Spring Boot/Tomcat)反向代理
upstream java_app { server 127.0.0.1:8080; server 127.0.0.1:8081;}
server { listen 80; server_name java.example.com;
location / { proxy_pass http://java_app; 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;
# Java 应用通常需要较长的超时时间 proxy_connect_timeout 10s; proxy_read_timeout 300s; proxy_send_timeout 300s; }}7.4 前端 SPA(React/Vue)部署 + API 代理
server { listen 80; server_name spa.example.com;
root /var/www/spa/dist; index index.html;
# API 请求代理到后端 location /api/ { proxy_pass http://127.0.0.1:3000/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
# WebSocket 代理 location /ws/ { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
# SPA 路由:所有非文件请求都返回 index.html location / { try_files $uri $uri/ /index.html; }
# 缓存策略 location ~* \.(js|css)$ { expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; }
location ~* \.(png|jpg|jpeg|gif|ico|svg)$ { expires 7d; access_log off; }}8. 安全加固配置
8.1 基础安全头
server { listen 80; server_name example.com;
# 安全头 add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Content-Security-Policy "default-src 'self'" always;
location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }}8.2 限流配置
http { # 定义限流区:名称=one,每秒 10 个请求,内存 10m limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
server { listen 80; server_name api.example.com;
location / { # 限流:使用 one 区,突发 20 个请求,延迟处理 limit_req zone=one burst=20 nodelay;
proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }}限流参数说明:
rate=10r/s:限制每秒 10 个请求burst=20:允许突发 20 个请求排队nodelay:突发请求不延迟处理(立即处理,但超过 burst 的请求被拒绝)
8.3 IP 黑白名单
server { listen 80; server_name example.com;
# 黑名单(拒绝访问) deny 192.168.1.100; deny 10.0.0.0/8;
# 白名单(允许访问,配合 deny all 使用) allow 203.0.113.0/24; allow 198.51.100.50; deny all; # 拒绝其他所有 IP
location / { proxy_pass http://127.0.0.1:3000; }}8.4 隐藏 Nginx 版本号
# 在 http 块中http { server_tokens off; # 隐藏 Nginx 版本号(响应头中不显示版本) # ...}9. 性能优化
9.1 worker 进程优化
user www-data;worker_processes auto; # 自动设置为 CPU 核心数worker_cpu_affinity auto; # 自动绑定 CPU 核心worker_rlimit_nofile 65535; # 每个 worker 最大文件描述符数
events { worker_connections 4096; # 每个 worker 最大连接数 use epoll; # Linux 下使用 epoll(高效事件模型) multi_accept on; # 一次 accept 多个连接}
http { sendfile on; # 启用 sendfile(零拷贝传输) tcp_nopush on; # 优化网络传输 tcp_nodelay on; # 禁用 Nagle 算法(低延迟) keepalive_timeout 65; # 保持连接超时 keepalive_requests 1000; # 每个连接最大请求数 # ...}9.2 开启 Gzip 压缩
http { gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; # 压缩级别 1-9,6 是性价比最高的 gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 1024; # 小于 1KB 不压缩(压缩收益低)}9.3 开启 Brotli 压缩(推荐)
Brotli 是 Google 开发的压缩算法,比 Gzip 压缩率高 20-30%:
# 需要 Nginx 编译时启用 ngx_brotli 模块http { brotli on; brotli_comp_level 6; brotli_types text/plain text/css application/json application/javascript text/xml;}10. 错误排查
10.1 常见错误与解决方案
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
502 Bad Gateway | 后端服务未启动或端口错误 | 检查后端服务是否运行:systemctl status yourapp |
502 Bad Gateway | 后端服务运行但 Nginx 无法连接 | 检查防火墙:ufw status;检查 SELinux:getenforce |
504 Gateway Timeout | 后端响应超时 | 增大 proxy_read_timeout |
413 Request Entity Too Large | 上传文件超过限制 | 设置 client_max_body_size 100M; |
404 Not Found(代理后) | proxy_pass 路径配置错误 | 检查 proxy_pass 路径匹配规则(见第 2.2 节) |
| 静态资源 404 | root 或 alias 路径错误 | 检查文件路径是否正确;注意 root 和 alias 的区别 |
| 后端获取不到真实 IP | 未配置 X-Real-IP 头 | 添加 proxy_set_header X-Real-IP $remote_addr; |
| WebSocket 连接失败 | 未配置 Upgrade 头 | 添加 WebSocket 完整配置(见第 6 节) |
| 配置修改后不生效 | 未 reload Nginx | 执行 nginx -s reload 或 systemctl reload nginx |
10.2 调试技巧
# 检查配置文件语法nginx -t
# 查看详细错误信息nginx -t 2>&1
# 重新加载配置(不中断服务)nginx -s reload# 或systemctl reload nginx
# 查看 Nginx 错误日志tail -f /var/log/nginx/error.log
# 查看访问日志tail -f /var/log/nginx/access.log
# 测试代理是否正常工作curl -I http://example.com
# 查看响应头中的自定义头(如 X-Cache-Status)curl -I http://example.com/api/test
# 测试真实 IP 传递是否正确# 在后端应用中打印 request.META 或 request.headers10.3 root vs alias 区别(经典坑)
# root:将 location 路径附加到 root 路径后location /static/ { root /var/www/app; # 请求 /static/logo.png → 查找 /var/www/app/static/logo.png}
# alias:用 alias 路径替换 location 路径location /static/ { alias /var/www/app/static/; # 请求 /static/logo.png → 查找 /var/www/app/static/logo.png # 注意:alias 路径末尾必须有 /(如果 location 末尾有 /)}记忆口诀: root 是拼接,alias 是替换。
11. 生产环境完整配置模板
# /etc/nginx/nginx.conf(部分)user www-data;worker_processes auto;worker_rlimit_nofile 65535;
events { worker_connections 4096; use epoll; multi_accept on;}
http { # 基础优化 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; keepalive_requests 1000; types_hash_max_size 2048;
# 隐藏版本号 server_tokens off;
# Gzip 压缩 gzip on; gzip_vary on; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript;
# 缓存区 proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=60m;
# 限流区 limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
# 引入站点配置 include /etc/nginx/sites-enabled/*;}# /etc/nginx/sites-available/myapp(生产完整配置)upstream app_backend { least_conn; server 127.0.0.1:3000 max_fails=2 fail_timeout=10s; server 127.0.0.1:3001 max_fails=2 fail_timeout=10s; server 127.0.0.1:3002 max_fails=2 fail_timeout=10s; server 127.0.0.1:3003 backup;}
# HTTP 跳转 HTTPSserver { listen 80; listen [::]:80; server_name myapp.com www.myapp.com; return 301 https://$host$request_uri;}
# HTTPS 主配置server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name myapp.com www.myapp.com;
# SSL 证书(Let's Encrypt) ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d;
# 安全头 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always;
# 上传限制 client_max_body_size 50M;
# 静态资源 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { root /var/www/myapp/dist; expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; access_log off; }
# API 代理(带缓存 + 限流) location /api/ { limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://app_backend; 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_connect_timeout 5s; proxy_read_timeout 60s;
# 缓存 proxy_cache api_cache; proxy_cache_valid 200 1m; proxy_cache_valid any 0s; add_header X-Cache-Status $upstream_cache_status; }
# WebSocket 代理 location /ws/ { proxy_pass http://app_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 3600s; }
# 健康检查 location /health { access_log off; return 200 "OK\n"; add_header Content-Type "text/plain"; }
# 默认代理 location / { proxy_pass http://app_backend; 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; }}12. 最佳实践清单
proxy_set_header四件套必配:Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto- 超时时间要调整: 默认 60s 可能不够,API 场景建议
proxy_read_timeout 60s,WebSocket 场景建议3600s proxy_pass路径规则要清楚: 带 URI 和不带 URI 的行为完全不同(见第 2.2 节)- 负载均衡用
least_conn: 比默认轮询更智能,能动态感知后端负载 - SSL 终止在 Nginx 做: 后端只需处理 HTTP,简化证书管理
- 开启 HTTP/2:
listen 443 ssl http2一行搞定,性能提升明显 - 静态资源让 Nginx 直接提供: 不经过后端应用,大幅降低后端压力
- 配置缓存: 对 API 响应和静态资源启用
proxy_cache,减少后端负载 - 隐藏 Nginx 版本号:
server_tokens off减少信息泄露 - 修改配置后先
nginx -t再 reload: 避免配置错误导致服务中断
13. 总结
Nginx 反向代理是现代 Web 部署的核心技能。掌握本文内容后,你可以:
- 将任何后端应用(Node.js/Python/Java/Go)通过 Nginx 暴露给外部访问
- 搭建负载均衡集群,提升服务可用性和并发能力
- 配置 HTTPS 终止,简化证书管理
- 支持 WebSocket 长连接
- 通过缓存和压缩优化性能
- 通过限流和安全头加固服务安全
推荐学习路径:
- 先配置一个基础反向代理(第 2 节)
- 再配置负载均衡(第 3 节)
- 接着配置 HTTPS(第 4 节)
- 最后按生产模板(第 11 节)完善配置
推荐阅读:
Nginx 反向代理配置实战完全指南:从入门到生产部署 | 2026 最新
https://971918.xyz/posts/docs/nginx-reverse-proxy-guide/