适用场景

线上服务通过 Nginx 反向代理访问,业务侧反馈接口偶发失败、页面加载慢,Nginx 访问日志里出现大量 502504499 状态码。

这类问题很常见,但三个状态码代表的方向并不一样:

  • 502 Bad Gateway:Nginx 作为网关访问上游失败,通常是上游服务异常、连接失败、协议异常。
  • 504 Gateway Timeout:Nginx 等上游响应超时,通常是上游处理慢、数据库慢、网络慢。
  • 499:客户端主动断开连接,这是 Nginx 自定义状态码,通常是客户端等不及、网络中断或前端超时先到了。

现象描述

常见告警或日志表现:

upstream prematurely closed connection while reading response header from upstream
connect() failed (111: Connection refused) while connecting to upstream
upstream timed out (110: Connection timed out) while reading response header from upstream

访问日志中可能看到:

10.0.0.1 - - [07/Jul/2026:10:21:33 +0800] "GET /api/order HTTP/1.1" 502 157 "-" "curl/8.0"
10.0.0.1 - - [07/Jul/2026:10:22:10 +0800] "POST /api/pay HTTP/1.1" 504 167 "-" "Mozilla/5.0"
10.0.0.1 - - [07/Jul/2026:10:23:02 +0800] "GET /api/report HTTP/1.1" 499 0 "-" "Mozilla/5.0"

可能原因

502 常见原因

  • 上游服务进程挂了,端口没有监听;
  • upstream 配置的地址或端口错误;
  • 上游服务主动断开连接;
  • 上游返回了不符合 HTTP 协议的响应;
  • Nginx 到上游的连接数、文件描述符或连接池耗尽;
  • 后端服务发布、重启、崩溃期间短暂不可用。

504 常见原因

  • 上游接口处理时间超过 Nginx 超时时间;
  • 数据库慢查询、锁等待、连接池耗尽;
  • 后端依赖第三方接口超时;
  • 上游机器 CPU、内存、磁盘 I/O 压力高;
  • Nginx 到上游网络延迟高或丢包;
  • proxy_read_timeout 配置过短。

499 常见原因

  • 客户端主动取消请求;
  • 浏览器、App、网关、负载均衡的超时时间短于 Nginx;
  • 后端响应太慢,用户刷新或关闭页面;
  • 移动网络抖动;
  • 前端重复请求后取消旧请求;
  • 上游慢导致客户端先断开。

排查思路

1. 先按状态码分组统计

awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

如果日志格式不同,需要把 $9 替换成实际状态码字段。

也可以统计最近 10 分钟的错误接口:

grep ' 50[24] ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -20

判断重点:

  • 只有少数接口异常,优先看业务接口和上游服务;
  • 所有接口都异常,优先看 Nginx、上游集群、网络、发布变更;
  • 某一台上游异常,优先看 upstream 分布和单机状态。

2. 查看 Nginx error.log

tail -f /var/log/nginx/error.log

按关键词过滤:

egrep -i "upstream|timed out|refused|reset|prematurely|no live upstreams" /var/log/nginx/error.log | tail -100

常见日志含义:

  • connect() failed (111: Connection refused):上游端口拒绝连接,服务可能没起来。
  • upstream timed out:上游响应超时,重点看后端耗时。
  • upstream prematurely closed connection:上游提前关闭连接,可能是应用崩溃、超时或连接被重置。
  • no live upstreams:Nginx 认为没有可用上游,检查 upstream 健康状态和配置。

3. 检查上游端口是否可连

curl -v http://127.0.0.1:8080/health

如果上游在其他机器:

curl -v --connect-timeout 3 http://10.0.0.12:8080/health
nc -vz 10.0.0.12 8080

判断:

  • Connection refused:端口没监听或服务拒绝;
  • Connection timed out:网络不通、防火墙、路由或服务卡死;
  • 能连但响应慢:继续查后端服务和依赖。

4. 检查上游服务状态

systemctl status app
journalctl -u app -n 200 --no-pager

如果是容器:

docker ps
docker logs --tail=200 app

如果是 Kubernetes:

kubectl get pod -o wide
kubectl describe pod <pod-name>
kubectl logs <pod-name> --tail=200

重点看:

  • 是否频繁重启;
  • 是否 OOMKilled;
  • 是否连接数据库失败;
  • 是否发布后启动失败;
  • 是否健康检查失败。

5. 分析接口耗时

建议 Nginx 日志格式里加入 upstream 耗时字段:

log_format main '$remote_addr $request_time $upstream_response_time '
                '$upstream_addr $status "$request"';

查看慢请求:

awk '$2 > 3 {print $0}' /var/log/nginx/access.log | tail -50

如果 $request_time 很高,$upstream_response_time 也很高,说明上游处理慢。

如果 $request_time 高但 $upstream_response_time 为空,需要检查客户端连接、Nginx 自身或日志格式。

常用命令

查看 502/504/499 数量

awk '{code[$9]++} END {for (c in code) print c, code[c]}' /var/log/nginx/access.log | sort -nr

查看错误最多的 URL

awk '$9 ~ /^(499|502|504)$/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20

查看错误最多的上游

如果日志里有 $upstream_addr 字段:

awk '$9 ~ /^(502|504)$/ {print $NF}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

检查 Nginx 配置

nginx -t
nginx -T | less

查看连接状态

ss -antp | grep nginx | head
ss -s

查看文件描述符限制

ulimit -n
cat /proc/$(pidof nginx | awk '{print $1}')/limits | grep "open files"

定位示例

某服务出现大量 504,先看访问日志:

awk '$9 == 504 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

发现集中在:

120 /api/report/export

继续看上游耗时:

grep '/api/report/export' /var/log/nginx/access.log | tail -20

发现:

request_time=60.001 upstream_response_time=60.000 status=504

说明请求基本都是卡到 60 秒超时。继续查后端日志,发现 SQL 查询耗时 70 秒以上,根因不是 Nginx,而是报表接口查询慢。

处理方式:

  • 临时提高接口超时时间只能缓解,不是根治;
  • 优先优化 SQL、增加索引、限制导出范围;
  • 对耗时任务改成异步导出;
  • 前端改成提交任务后轮询结果,避免长连接等待。

修复方案

502 修复方向

  • 恢复上游服务;
  • 修正 upstream 地址和端口;
  • 检查服务启动日志;
  • 调整发布流程,避免无可用实例;
  • 增加健康检查和优雅下线;
  • 检查连接数和文件描述符限制。

504 修复方向

  • 优化慢接口、慢 SQL、锁等待;
  • 检查数据库、缓存、第三方依赖;
  • 调整 proxy_connect_timeoutproxy_read_timeoutproxy_send_timeout
  • 对长耗时任务改异步;
  • 给上游服务增加容量或限流。

示例:

location /api/ {
    proxy_connect_timeout 3s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
    proxy_pass http://backend;
}

499 修复方向

  • 对齐客户端、网关、Nginx、上游的超时时间;
  • 优化慢接口,减少客户端等待;
  • 排查移动端或公网链路抖动;
  • 检查前端是否主动取消重复请求;
  • 对大文件下载、报表导出等场景改异步或断点续传。

预防措施

  1. Nginx access log 必须记录 $request_time$upstream_response_time$upstream_addr
  2. 499502504 分开建告警,不要混在一个 5xx 告警里。
  3. 发布系统要支持健康检查、灰度、失败自动回滚。
  4. 上游服务要提供 /health/ready 接口。
  5. 慢接口要有独立监控,尤其是导出、查询、批量操作。
  6. Nginx、网关、客户端、后端的超时时间要统一设计。

总结

排查 Nginx 502504499 时,不要只盯着 Nginx。

可以先记住这个方向:

  • 502:上游连不上或响应异常;
  • 504:上游太慢,Nginx 等超时;
  • 499:客户端先断开,通常是客户端超时或用户取消。

实际处理时,先按状态码和 URL 聚合,再结合 error.log、上游健康检查、接口耗时和后端日志,基本可以很快缩小范围。