适用场景
线上服务通过 Nginx 反向代理访问,业务侧反馈接口偶发失败、页面加载慢,Nginx 访问日志里出现大量 502、504 或 499 状态码。
这类问题很常见,但三个状态码代表的方向并不一样:
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_timeout、proxy_read_timeout、proxy_send_timeout; - 对长耗时任务改异步;
- 给上游服务增加容量或限流。
示例:
location /api/ {
proxy_connect_timeout 3s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_pass http://backend;
}
499 修复方向
- 对齐客户端、网关、Nginx、上游的超时时间;
- 优化慢接口,减少客户端等待;
- 排查移动端或公网链路抖动;
- 检查前端是否主动取消重复请求;
- 对大文件下载、报表导出等场景改异步或断点续传。
预防措施
- Nginx access log 必须记录
$request_time、$upstream_response_time、$upstream_addr。 - 对
499、502、504分开建告警,不要混在一个 5xx 告警里。 - 发布系统要支持健康检查、灰度、失败自动回滚。
- 上游服务要提供
/health或/ready接口。 - 慢接口要有独立监控,尤其是导出、查询、批量操作。
- Nginx、网关、客户端、后端的超时时间要统一设计。
总结
排查 Nginx 502、504、499 时,不要只盯着 Nginx。
可以先记住这个方向:
502:上游连不上或响应异常;504:上游太慢,Nginx 等超时;499:客户端先断开,通常是客户端超时或用户取消。
实际处理时,先按状态码和 URL 聚合,再结合 error.log、上游健康检查、接口耗时和后端日志,基本可以很快缩小范围。
Discussion
评论