网站能打开,但接口迟迟不返回,最后页面甩出一句「504 Gateway Time-out」——这不是服务器挂了,而是 Nginx 等上游等累了。504 的本质是反向代理在约定时间内没收到后端响应,问题几乎永远出在「Nginx 与后端的超时配置」或「后端自己太慢、卡死」上。按下面三步,基本能定位八成以上的 504。
504 和 502,先别混为一谈
很多人把 502 和 504 当成一回事,其实排错方向完全不同。502 是上游「给了个无效响应」或「直接断了」;504 是上游「一直没给响应,超时了」。先分清,才不会在错误的方向上浪费时间。
| 错误码 | 含义 | 常见根因 |
|---|---|---|
| 502 | 上游无有效响应 | PHP-FPM 进程崩了、上游服务挂掉 |
| 504 | 上游响应超时 | 后端慢查询、worker 耗尽、超时太短 |
三步定位上游卡点
顺着「Nginx 配置 → 后端进程 → 资源/网络」这个顺序查,最快。
→
→
# 1. 看 Nginx 错误日志,确认是超时
tail -f /var/log/nginx/error.log
# 典型输出:
# upstream timed out (110: Connection timed out) \
# while reading response header from upstream
# 2. 绕过 Nginx 直连后端,排除 Nginx 自身问题
curl -i http://127.0.0.1:8080/api/health
# 3. 看后端进程是否吃满 CPU / 内存
top -p $(pgrep -f "your-backend")
踩坑实录
上周一台 Docker 里的 Nginx 反代 PHP-FPM,接口偶发 504。我第一反应是调大 proxy_read_timeout 到 120s,结果没用。后来 docker logs 看到 PHP 日志里一条慢查询跑了 90 秒。根因是 FPM 的 pm.max_children 只有 5,并发一高请求就排队,前端直接等超时。把 children 调到 20、再给那条 SQL 加索引,504 消失。教训:504 往往不是 Nginx 的锅,是后端自己堵了。
常见根因与对策
常见问题
proxy_read_timeout 设多大合适?
普通接口 60s 内够用;报表、导出、批量类可放宽到 300s,但别无限大,否则一个慢请求会拖垮整个连接池。
502 和 504 同时出现怎么排?
先按 502 的思路查上游是否还活着(直连端口、看进程),确认存活后再按 504 调超时和后端性能。
如果这篇帮你省了一次半夜告警,欢迎在 fenij.com 留言说说你踩过的 504 坑,或者推荐你想看的下一篇排障主题。