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 最简配置#

/etc/nginx/sites-available/myapp
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 匹配部分
  • 正则 locationproxy_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_failsfail_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 自动跳转 HTTPS
server {
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 自动证书(推荐)#

Terminal window
# 安装 certbot
apt install certbot python3-certbot-nginx # Debian/Ubuntu
yum 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 跳转 HTTPS
server {
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缓存过期但后端不可用,返回过期缓存
BYPASSproxy_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 进程优化#

/etc/nginx/nginx.conf
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 节)
静态资源 404rootalias 路径错误检查文件路径是否正确;注意 rootalias 的区别
后端获取不到真实 IP未配置 X-Real-IP添加 proxy_set_header X-Real-IP $remote_addr;
WebSocket 连接失败未配置 Upgrade 头添加 WebSocket 完整配置(见第 6 节)
配置修改后不生效未 reload Nginx执行 nginx -s reloadsystemctl reload nginx

10.2 调试技巧#

Terminal window
# 检查配置文件语法
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.headers

10.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 跳转 HTTPS
server {
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. 最佳实践清单#

  1. proxy_set_header 四件套必配: HostX-Real-IPX-Forwarded-ForX-Forwarded-Proto
  2. 超时时间要调整: 默认 60s 可能不够,API 场景建议 proxy_read_timeout 60s,WebSocket 场景建议 3600s
  3. proxy_pass 路径规则要清楚: 带 URI 和不带 URI 的行为完全不同(见第 2.2 节)
  4. 负载均衡用 least_conn 比默认轮询更智能,能动态感知后端负载
  5. SSL 终止在 Nginx 做: 后端只需处理 HTTP,简化证书管理
  6. 开启 HTTP/2: listen 443 ssl http2 一行搞定,性能提升明显
  7. 静态资源让 Nginx 直接提供: 不经过后端应用,大幅降低后端压力
  8. 配置缓存: 对 API 响应和静态资源启用 proxy_cache,减少后端负载
  9. 隐藏 Nginx 版本号: server_tokens off 减少信息泄露
  10. 修改配置后先 nginx -t 再 reload: 避免配置错误导致服务中断

13. 总结#

Nginx 反向代理是现代 Web 部署的核心技能。掌握本文内容后,你可以:

  • 将任何后端应用(Node.js/Python/Java/Go)通过 Nginx 暴露给外部访问
  • 搭建负载均衡集群,提升服务可用性和并发能力
  • 配置 HTTPS 终止,简化证书管理
  • 支持 WebSocket 长连接
  • 通过缓存和压缩优化性能
  • 通过限流和安全头加固服务安全

推荐学习路径:

  1. 先配置一个基础反向代理(第 2 节)
  2. 再配置负载均衡(第 3 节)
  3. 接着配置 HTTPS(第 4 节)
  4. 最后按生产模板(第 11 节)完善配置

推荐阅读:

Nginx 反向代理配置实战完全指南:从入门到生产部署 | 2026 最新
https://971918.xyz/posts/docs/nginx-reverse-proxy-guide/
作者
九所长
发布于
2026-07-01
许可协议
CC BY-NC-SA 4.0