504 是什么
504 Gateway Timeout 表示作为网关或代理的服务器,等待上游响应超过了自身设定的超时时间。RFC 9110 §15.6.5 的语义很明确:上游是可达的,只是没在期限内给出完整响应,这与 502 的连不上或收到无效响应不同。它的根因几乎总在上游的处理耗时——慢查询、外部依赖卡住、锁等待,或者后端本身出现了慢请求堆积。
基本信息
| 名称 | 504 Gateway Timeout(RFC 9110 §15.6.5) |
|---|---|
| 作用 | 网关等待上游响应超时 |
| 与 502 区别 | 502 是连不上或响应非法,504 是能连上但太慢 |
| 常见配置 | 网关到上游的读取超时、上游服务器的处理时限 |
| 第一现场 | 访问日志中的上游响应时间与慢查询日志 |
典型成因
- 慢查询:缺少索引或数据量增长后,单条语句耗时超过阈值
- 外部依赖卡住:调用第三方接口或内部服务没有设置超时
- 锁等待:长事务持有行锁,后续请求排队等到超时
- 后端进程数不足:请求排队,最后一个请求等待时间叠加
- 导出或报表类长任务:同步执行天然超过网关超时
- 磁盘或网络抖动:读写变慢,把整条链路拖长
定位慢在哪一段
定位慢在哪一段
# 用访问日志里的上游响应时间排序,找出最慢的接口
awk '{print $7, $upstream_response_time, $request_time}' /var/log/nginx/access.log | sort -k2 -rn | head
# 直接在后端上按同一请求测一次,判断是网关侧还是上游侧的问题
curl -s -o /dev/null -w '%{time_total}\n' http://127.0.0.1:8000/api/report
# 数据库侧确认是否存在长时间运行的语句
tail -n 100 /var/log/mysql/slow.log常见根因与处置
| 现象 | 可能成因 | 处置方向 |
|---|---|---|
| 只有个别接口超时 | 慢查询或外部依赖无超时 | 加索引、给依赖调用设超时与熔断 |
| 全部接口逐渐变慢 | 连接池打满、进程数不足 | 扩容或调大并发,并补限流 |
| 固定时段集中超时 | 定时任务与业务抢资源 | 错峰执行或把任务移到独立资源 |
| 长任务必超时 | 网关超时阈值低于任务时长 | 改为异步受理加进度查询 |
调大超时阈值只是止痛:它把故障从「报错」变成「用户长时间等待」,同时占用更多连接。正确顺序是先确认上游是否收到请求,再找出慢在数据库、依赖还是自身代码,最后才评估阈值是否合理。
网关超时小于业务处理时间是常见的架构陷阱:导出、批量处理这类天然耗时数分钟的任务必须异步化,用受理码加进度查询替代同步等待,否则无论怎么调阈值都会在大数据量下失守。
阈值该怎么定
- 阈值要大于该接口正常情况下的最长耗时,不能照搬其他接口的数值
- 给外部依赖单独设更短的超时,避免一个慢依赖占满网关的等待时间
- 用分位数而不是平均值来定阈值,平均值会掩盖长尾请求
- 长任务一律改成异步受理加进度查询,不要靠放大阈值硬扛
两个耗时指标怎么读
| 指标 | 含义与用法 |
|---|---|
| 上游响应时间 | 网关侧记录的等待上游耗时,是判断超时根因的第一指标 |
| 请求总耗时 | 包含排队与网关自身开销,与前者之差能看出网关侧是否有额外消耗 |
| 上游连接时间 | 建立上游连接的花费,偏大说明网络或后端接受连接慢 |
与相邻错误怎么区分
- 连接都建立不起来属于网关错误,能建立连接但没在期限内响应才是超时
- 出现超时且上游日志里有异常堆栈,说明问题在上游代码而不是超时配置本身
- 只有超时没有异常日志,优先去看慢查询与外部依赖的耗时分布