Nginx proxy_pass反向代理与upstream负载均衡配置详解(实战指南)

深入拆解 Nginx proxy_pass 和 upstream 配置的每一个细节:路径斜杠的陷阱、负载均衡策略的适用场景、健康检查实现方法,以及生产环境部署前的验证与回滚方案。不堆概念,只给可直接落地的命令与解释。

Nginx proxy_pass反向代理与upstream负载均衡配置详解(实战指南)
封面图:ZuCDN · ZuCDN 原创

反向代理与负载均衡是 Nginx 最核心的两项功能,但配置中的细节陷阱——比如 proxy_pass 末尾是否带斜杠、upstream 的 max_fails 如何影响故障转移、down 状态的实际用途——才是决定线上稳定性的关键。本文不讲基础入门,直接聚焦配置实操中的真实问题、风险点和验证手段。

一、proxy_pass 语法:一个斜杠的差异

proxy_pass 的行为取决于代理地址结尾是否有斜杠。很多人在这里踩坑:前端报告 404,后端却正常。

1.1 带斜杠,即替换 URI 的路径部分

location /api/ {
    proxy_pass http://backend/;
}

当请求匹配 /api/user 时,Nginx 会将 /api/ 替换为 /,最终向后端发送 /user适用场景:后端服务根路径直接响应,不需要前缀。

1.2 不带斜杠,完整传递 URI

location /api/ {
    proxy_pass http://backend;
}

此时 Nginx 传递完整 URI /api/user 给后端。适用场景:后端服务需要保留原路径,例如多版本 API 映射。

重要风险:如果 proxy_pass 使用了变量(如 $request_uri),则无论是否带斜杠,URI 都不会被自动拼接,必须手动处理。另外,使用正则表达式 location 时,proxy_pass 中不能带斜杠,除非在尾部额外加 /(需要 Nginx 0.7.40 以上)。

二、upstream 负载均衡:策略选择与参数陷阱

upstream 块配置的后端组配合 proxy_pass 才能实现负载均衡。但不同策略对应用场景敏感,错误的选择可能导致雪崩。

2.1 五种负载均衡策略

  • 轮询(默认):请求按顺序分发。适合后端性能均等、无状态场景。短板是慢请求会累积,造成负载不均。
  • weight 加权server 10.0.1.1 weight=3; 适合异构服务器。
  • ip_hash:基于客户端 IP 哈希,保证同一用户固定到后端。用于 session 未外置的传统应用。注意:如果后端上线/下线导致哈希变化,连接断裂。
  • least_conn:发给当前活跃连接数最少的后端。配合 keepalive 连接池时需谨慎评估,因为 Nginx 自身连接数不等于后端实际压力。
  • random (Nginx 1.16+):随机选择,可配合 two 参数(如 random two least_conn)实现两阶段随机选最优,抗突发流量。

2.2 server 指令的隐式参数

upstream backend {
    server 10.0.1.1 max_fails=3 fail_timeout=30s backup;
    server 10.0.1.2 resolve;
}

max_fails 与 fail_timeout:默认 max_fails=1,fail_timeout=10s。表示 10 秒内失败 1 次就标记为不可用。这在高并发短连接场景可能误判(偶发 TCP RST),建议增大 max_fails=3。改完后必须重启 Nginx 生效。

backup:标记为备用,仅在所有非 backup 服务器均不可用时启用。常用于跨机房冷备。

resolve:配合 resolver 域名解析,用于动态变更的后端 IP(如 Kubernetes 无头服务)。注意要同时设置 resolver 指令且 valid=30s 控制刷新间隔。

三、复杂场景:HTTPS 后端、健康检查与故障转移

3.1 代理到 HTTPS 后端

location / {
    proxy_pass https://backend;
    proxy_ssl_verify on;
    proxy_ssl_trusted_certificate /etc/nginx/ssl/backend-ca.crt;
    proxy_ssl_server_name on;  # 若后端要求 SNI
}

如果后端是自签证书,关闭 proxy_ssl_verify 会带来中间人风险。生产环境建议用内部 CA 签名,通过双向证书链验证。

3.2 健康检查

Nginx Plus 有内置 active health checks,开源版需通过 ngx_http_healthcheck_module(第三方)或使用 Proxy Protocol 做外部监控。常见替代方案:

  • 利用 proxy_next_upstream 实现被动健康检查:
http {
    upstream backend {
        server 10.0.1.1 max_fails=2 fail_timeout=15s;
        server 10.0.1.2 max_fails=2 fail_timeout=15s;
    }
    server {
        location / {
            proxy_pass http://backend;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
            proxy_next_upstream_tries 3;
            proxy_connect_timeout 5s;
        }
    }
}

当后端返回 500 或超时,Nginx 自动重试下一个后端。注意:proxy_next_upstream_tries 过大可能放大对后端的压力;配合 proxy_cache_use_stale 可以回退到缓存而非重试。

3.3 故障转移与优雅下线

需要临时摘除后端时,不要直接 kill nginx -s reload 会丢失正在处理的长连接。正确做法:

  1. 在 upstream 中添加 server 10.0.1.1 down;
  2. 执行 nginx -s reload
  3. 等待已有连接处理完毕(可监控后端 TCP 连接数归零);
  4. 停止后端服务。

注意:如果后端使用了 keepalive,Nginx 与后端的连接池并不会立刻消失,down 参数只阻止新请求分配到该地址。重载期间已有 keepalive 连接仍在,后端停止后这些连接可能引发 TIME_WAIT 堆积。

四、配置验证与回滚方案

4.1 验证配置正确性

# 语法检查
nginx -t -c /etc/nginx/nginx.conf
# 若报错,查看具体行号

# 模拟请求测试(使用 curl + Host 头)
curl -H "Host: example.com" http://127.0.0.1/api/test

# 检查是否命中预期后端:观察后端日志
# 或者启用 Nginx 调试日志
nginx -c /etc/nginx/nginx.conf -g "error_log /var/log/nginx/debug.log debug;"

生产环境建议在灰度流量中使用 split_clientsmap 按比例路由,验证新配置稳定性。

4.2 快速回滚

不要只依赖 `nginx -s reload` 的惰性加载。给配置文件建立版本化备份:

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.$(date +%Y%m%d%H%M)
# 或者使用 git 管理 /etc/nginx 目录

# 回滚步骤
cp /etc/nginx/nginx.conf.202410150830 /etc/nginx/nginx.conf
nginx -t && nginx -s reload

如果改动导致大量 502,不要反复 reload。直接恢复旧配置后,应同时检查后端的负载情况——故障可能源自后端而非配置。

五、性能调优与常见问题

5.1 代理缓冲区

proxy_buffer_size 4k;
proxy_buffering on;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;

当后端响应 header 很大(如 Set-Cookie 过多),`proxy_buffer_size` 过小会返回 502。动态接口建议 16k,静态接口保持默认即可。

5.2 Timeout 配置

proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;

对于长轮询或 WebSocket 场景,必须增大 read_timeout 至少到 1800s,并配合 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";。注意:开启 WebSocket 代理后,upstream 的 keepalive 需要额外配置 keepalive 16; 以复用连接。

5.3 常见错误排查

  • 502 Bad Gateway:大概率后端无响应或 Nginx 无法连接。检查后端监听地址、防火墙、proxy_pass 协议(http/https 不匹配)。
  • 504 Gateway Time-out:后端响应超时。先检查后端处理速度,再考虑增大 proxy_read_timeout。
  • 负载不均:排除轮询下的 keepalive 粘性。若使用 ip_hash,检查是否存在超级 IP(办公出口 IP 被哈希到同一后端)。
  • SSL 握手失败:确认 proxy_ssl_server_name 是否开启,后端证书是否受信任。

本文所有配置均基于 Nginx 1.18.0 测试,部分特性(如 random two)要求更高版本。生产环境请先做小范围灰度验证,然后再全量发布。配置本身不复杂,真正复杂的是在故障发生时,能够快速定位是配置问题还是后端问题——这也是给配置加版本号的意义所在。

延伸阅读