案例 Nginx 502/504 排障:先按 error.log 关键字分流,别急着重启

2026-09-23 21:02:57

Nginx 502/504 排障:先按 error.log 关键字分流,别急着重启

502 和 504 都表示 Nginx 作为网关没有拿到上游的正常响应,但病因不同。502 多发生在连接上游或读取响应的早期,504 更常见于上游没在规定时间内完成。

每次重启 Nginx 都是打地鼠:打掉的是眼前表象,病根要么在配置里,要么在后端进程,要么在网络那一层。同样,先把 proxy_read_timeout 从 60 秒改成 600 秒,也只是让连接占用更久。

先看 error.log 的关键字

  • connect() failed (111: Connection refused) while connecting to upstream:Nginx 找到了目标地址,但目标端口没有接受连接。
  • upstream timed out (110: Connection timed out) while connecting to upstream:建立上游连接就已超时,方向通常是地址、路由、防火墙或服务负载。
  • upstream timed out ... while reading response header from upstream:连接已建立,但后端迟迟没返回响应头,更像应用慢、数据库卡住或超时时间不匹配。
  • no live upstreams:配置中的上游没有可用节点,常见于 upstream 健康状态或服务发现问题。
  • recv() failed (104: Connection reset by peer):上游主动断开连接。

分层判断

现象判断方向
Connection refused目标主机可达,但端口没有服务监听。启动或修复后端,或改回正确端口。
Operation timed out不一定是进程退出,可能是容器网络、路由或防火墙问题。
返回 200、401 或应用自己的 500上游至少能响应,继续检查 Nginx 的 proxy_pass、请求头、路径和超时。
本机访问正常,Nginx 访问失败检查 Nginx 是否在容器、chroot 或其他网络命名空间中;127.0.0.1 指向的是 Nginx 自己所在的环境,不一定是宿主机。
本机访问 Nginx 502,直连 upstream 也失败问题在 upstream。
本机访问 Nginx 504,直连 upstream 响应慢问题在 upstream 处理时长。
本机访问 Nginx 慢,直连 upstream 正常问题多半在 Nginx 配置、DNS、连接复用或内核连接队列。

配置层面的常见错

  1. 上游地址/端口没同步:发版后服务换了端口,Nginx 还在打老端口。
  2. 协议写错:上游只提供 HTTP,却写成 https://;或者上游要求 TLS,Nginx 却用明文连接。
  3. 路径拼接不符合预期:proxy_pass http://backend;proxy_pass http://backend/; 在带 URI 的 location 下行为不同。

超时参数不要混为一谈

504 通常意味着请求已经进入代理流程,但上游没有及时完成。不要简单地把 proxy_read_timeout 从 60 秒改成 600 秒:如果真正原因是数据库锁、死循环或下游 API 卡死,你只是让连接占用更久,并把故障放大。

  • proxy_connect_timeout:控制建立连接的等待时间。
  • proxy_send_timeout:针对向上游发送请求。
  • proxy_read_timeout:针对两次读取上游响应之间的等待。

提高读取超时不会修复「端口没人监听」的 502,也不会解决应用本身崩溃。

location /api/ {
    proxy_pass http://backend_smart;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    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_send_timeout    30s;
    proxy_read_timeout    60s;

    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_next_upstream_tries 3;
    proxy_next_upstream_timeout 15s;

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

    proxy_intercept_errors on;
    error_page 502 503 504 = @fallback;
}
location @fallback {
    add_header Content-Type application/json;
    return 503 '{"error":503,"message":"Please try again later"}';
}

upstream 健康检查与故障转移:

upstream app_servers {
    server 10.0.0.2:9000 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:9000 max_fails=3 fail_timeout=30s;
}

max_fails 设置过小时,一次偶发断连就会让 Nginx 在 fail_timeout 时间内认为上游挂掉,持续返回 502。

HTTPS 两条链路

客户端到 Nginx,以及 Nginx 到 HTTPS 上游,是两条独立链路。客户端证书过期、域名不匹配时浏览器通常直接提示 TLS 错误;Nginx 连接 HTTPS 上游失败,会在 error log 中看到 SSL handshake、certificate verify 或协议错误,外观上可能被误认为 502。

确认这几点:证书未过期、SAN 包含访问域名、完整证书链已部署、proxy_ssl_server_name 与上游要求一致。不要为了绕过生产问题永久关闭证书验证。

日志字段要打全

没有 upstream_response_timeupstream_status,排 5xx 会很被动。access.log 里按状态码过滤 502/504,error.log 按关键字过滤:

grep -E "connect\(\) failed|upstream timed out|reset by peer|no live upstreams" /var/log/nginx/error.log | tail -100

真实案例:

  • 案例一:502,error.log 显示 connect() failed (110: Connection timed out),telnet 测试一切正常,最后发现云 SLB 与后端之间的健康检查出问题,SLB 认为后端不健康,把流量都打到同一台机器上,那台机器扛不住超时。
  • 案例二:发版后部分接口 502、部分正常,检查 upstream 地址没改,新服务在新端口,Nginx 还在打老端口。
  • 案例三:504 根因是慢 SQL。proxy_read_timeout 15 秒,业务方第一反应改成 60 秒;直连 upstream 同样慢,数据库里有多条全表扫描慢 SQL。正确做法是优化 SQL 或限流,而不是拉长超时。
复制全文 生成海报 Nginx 运维 排障 反向代理

推荐文章

程序员茄子在线接单