Nginx 反向代理:几个容易踩的坑
反向代理的配置本身不复杂,但线上出问题时,往往不是“能不能通”,而是“通得不对”。下面三个问题我遇到过不止一次。
一、代理超时,默认值不够用
Nginx 到上游的默认超时是 60 秒。遇到导出报表、图片处理这类长任务,上游还在算,Nginx 已经断了连接,浏览器看到的是 504。
常见做法是按路径单独放宽,而不是全局改大:
location /api/export/ {
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
只改需要长耗时的接口,其余保持默认,避免慢请求长期占住连接。
二、后端拿不到真实 IP
没做转发头配置时,后端看到的客户端地址永远是 127.0.0.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;
还要提醒一句:X-Forwarded-For 是可以被客户端伪造的。如果前面还有 CDN,后端只能信任来自已知代理网段的最后一跳,否则拿到的 IP 没有意义。
三、WebSocket 一连上就断
用 HTTP/1.1 的 Upgrade 升级连接,如果少了这两个头,握手能过去,随后很快断开:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
另外记得给 WebSocket 路径单独设置较长的 proxy_read_timeout,否则空闲几十秒后连接就被回收,客户端不停重连。
排查顺序
- 先看 Nginx 错误日志,确认是上游超时还是连接被拒
- 在服务器上用
curl -I直接请求上游端口,绕开 Nginx 判断 - 对比
proxy_pass结尾有没有斜杠,路径拼接经常在这里出错
最后一点:proxy_pass http://host/ 和 proxy_pass http://host 的行为不同,前者会替换掉 location 匹配的部分。改配置时最好一次只动一处,出问题好回滚。