Nginx 反向代理配置与 502 排查实战

举报
云上小栈 发表于 2026/10/24 00:18:52 2026/10/24
【摘要】 一、最小可用的反向代理配置下面是一段能直接上线的反向代理配置,挂在 conf.d/app.conf 里:server { listen 80; server_name app.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1...

一、最小可用的反向代理配置

下面是一段能直接上线的反向代理配置,挂在 conf.d/app.conf 里:

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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_send_timeout 60s;
    }
}

几个点必须说清楚:proxy_pass 结尾带不带 / 语义不同。写成 http://127.0.0.1:8080/ 会把 location 匹配到的前缀替换掉,写成 http://127.0.0.1:8080 则原样透传 URI。配置改完用 nginx -t 校验,再用 nginx -s reload 生效,不要用 restart,会断连接。

二、502 的三类根因

Nginx 返回 502 的含义只有一句:上游返回了无效响应,或连接根本没建起来。按发生位置分三类。

  • 连不上上游:端口没监听、进程挂了、防火墙拦截。用 ss -lntp | grep 8080 确认监听,用 curl -v http://127.0.0.1:8080/health 绕开 Nginx 直连验证。
  • 连上了但超时:上游处理超过 proxy_read_timeout。默认 60 秒,导出大文件或跑长 SQL 时很容易触发。
  • 上游主动断开:应用崩溃、被 OOM Killer 杀掉,或 PHP-FPM 进程池打满。

第一步永远是看日志:

tail -n 100 /var/log/nginx/error.log
grep -c ' 502 ' /var/log/nginx/access.log

error.log 里的 connect() failed (111: Connection refused) 是端口没人听;upstream timed out 是超时;recv() failed (104: Connection reset by peer) 是上游崩了。这三种指向完全不同的排查方向。

三、坑一:Host 头丢失导致上游 502

某次把应用从 IP 访问改成域名访问后,Nginx 全量 502,直连后端却正常。原因是没有配 proxy_set_header Host $host,Nginx 默认把 Host 设成 proxy_pass 里的地址,即 127.0.0.1:8080。后端的 Spring Boot 开了虚拟主机校验,认不出这个 Host 就直接 reset 连接。

验证方式是在后端抓包看请求头:

tcpdump -i lo -A -s 0 'tcp port 8080' | grep -i host

补上 proxy_set_header Host $host; 后恢复。如果后端还依赖真实 IP 做限流,X-Real-IP 和 X-Forwarded-For 也要一起加,否则日志里全是 127.0.0.1。

四、坑二:keepalive 没配,端口被 TIME_WAIT 占满

QPS 到 2000 左右时开始零星 502,error.log 报 Cannot assign requested address。这是 Nginx 到上游每次请求都新建 TCP 连接,短连接大量堆积在 TIME_WAIT,本地临时端口耗尽。

解决分两步。上游块里声明 keepalive:

upstream backend {
    server 127.0.0.1:8080;
    keepalive 64;
}

location / {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

注意 proxy_http_version 1.1 和清空 Connection 缺一不可,缺了 keepalive 不生效。另外把 net.ipv4.tcp_tw_reuse 设为 1。改完后 ss -s 观察,timewait 数量应从数万降到几百。

五、快速定位的检查顺序

  • nginx -t 确认配置语法,排除 reload 失败导致的旧配置继续服务。
  • curl -v http://127.0.0.1:8080/ 直连上游,确认应用本身是否健康。
  • tail -f /var/log/nginx/error.log 看具体错误串,按三类根因对号入座。
  • ss -lntp 和 ps aux | grep 应用名 确认进程与端口。
  • dmesg -T | grep -i oom 检查是否被系统杀掉。

小结

502 不是 Nginx 自己的错误,它只是转述上游的问题。配置层面把 Host、X-Forwarded-*、keepalive 三项固定下来,能消掉大部分线上 502。排查时先用 error.log 的错误串判断是连接失败、超时还是连接被重置,再决定去查端口、查超时参数还是查应用进程,不要一上来就调 proxy_read_timeout。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。