首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Nginx 502/504 排查实战:upstream 超时、连接耗尽与日志定位

Nginx 502/504 排查实战:upstream 超时、连接耗尽与日志定位

原创
作者头像
一只特立独行的兔先生
发布于 2026-10-18 09:20:52
发布于 2026-10-18 09:20:52
210
举报

现象与思路

线上访问偶发返回 502 Bad Gateway 或 504 Gateway Timeout,是 Nginx 反向代理场景最常见的故障之一。两者含义不同:

  • 502:Nginx 连不上上游,或上游异常关闭连接、返回了非法响应。
  • 504:Nginx 已连上上游,但在超时时间内没等到响应。

排查顺序:先看 Nginx 错误日志确认错误类型,再查上游服务状态,最后检查超时与连接参数。

第一步:从 error.log 读出根因

代码语言:bash
复制
tail -n 200 /var/log/nginx/error.log | grep -E "upstream|connect\(\)"

常见日志与含义:

日志关键字

含义

方向

connect() failed (111: Connection refused)

上游端口无进程监听

上游进程挂了或端口配错

upstream timed out (110: Connection timed out) while connecting

连接上游超时

网络、安全组、上游 backlog 满

upstream timed out ... while reading response header

等待响应超时

上游处理慢

upstream prematurely closed connection

上游中途断开

上游崩溃、被 OOM、请求体过大

no live upstreams

所有节点被标记不可用

max_fails 触发摘除

第二步:确认上游本身是否健康

绕过 Nginx,直接请求上游并计时:

代码语言:bash
复制
curl -o /dev/null -s -w "code=%{http_code} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n" http://127.0.0.1:8080/health
ss -lnt sport = :8080
  • 端口没监听:查进程是否被重启、被 OOM Kill(dmesg -T | grep -i oom)。
  • 监听但 Recv-Q 接近 Send-Q:accept 队列已满,应用处理不过来,需扩容或调大应用 backlog。
  • ttfb 很大:问题在应用或其依赖(数据库、缓存),而不是 Nginx。

第三步:检查 Nginx 超时与连接参数

代码语言:nginx
复制
location /api/ {
    proxy_pass http://backend;
    proxy_connect_timeout 3s;
    proxy_read_timeout   60s;
    proxy_send_timeout   60s;
    proxy_http_version   1.1;
    proxy_set_header     Connection "";
}

upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=10s;
    keepalive 64;
}

要点:

  • proxy_read_timeout 默认 60 秒,长耗时接口(导出、报表)会触发 504。优先把长任务改异步,而不是无限加大超时。
  • 使用 keepalive 时必须配合 proxy_http_version 1.1 与清空 Connection 头,否则连接无法复用,高并发下会堆积 TIME_WAIT 与端口耗尽。
  • max_fails/fail_timeout 会在上游短暂抖动后把节点摘除,若只有一个节点,会持续返回 502。

第四步:用访问日志量化问题

在 log_format 中加入上游耗时字段:

代码语言:nginx
复制
log_format main '$remote_addr "$request" $status '
                'rt=$request_time urt=$upstream_response_time uct=$upstream_connect_time '
                'up=$upstream_addr';

统计 5xx 分布与最慢请求:

代码语言:bash
复制
awk '$9 ~ /^50[24]$/ {print $9, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

(此命令中字段位置取决于你的 log_format,需按实际调整。) urt 接近 proxy_read_timeout 说明上游确实慢;uct 偏大则是连接阶段问题。

第五步:文件描述符与系统限制

高并发下 error.log 出现 Too many open files 或 worker_connections are not enough:

代码语言:bash
复制
cat /proc/$(pgrep -o nginx)/limits | grep "open files"
sysctl net.core.somaxconn net.ipv4.ip_local_port_range
代码语言:nginx
复制
worker_rlimit_nofile 65535;
events { worker_connections 10240; }

同时确认 systemd 单元的 LimitNOFILE 是否足够,否则 nginx.conf 中的设置不会生效。

排查清单

  1. error.log 判断类型:refused / timed out / prematurely closed。
  2. 绕过 Nginx 直连上游,区分网关问题与应用问题。
  3. 核对 proxy_*_timeout、keepalive、max_fails。
  4. 日志加入 $upstream_* 字段做量化。
  5. 检查文件描述符、somaxconn、端口范围。
  6. 修改后 nginx -t && nginx -s reload,观察 5xx 是否回落。

小结

502 多半是"连不上或被中断",504 多半是"等不到"。先看日志分类,再分层验证上游,最后才调参数,避免盲目加大超时掩盖真实性能问题。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 现象与思路
  • 第一步:从 error.log 读出根因
  • 第二步:确认上游本身是否健康
  • 第三步:检查 Nginx 超时与连接参数
  • 第四步:用访问日志量化问题
  • 第五步:文件描述符与系统限制
  • 排查清单
  • 小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档