间歇性 504:超时配置藏在哪几层
发布时间:2026-06-24 16:41       
更新时间:2026-06-24 20:06
502 是后端挂了,504 是后端活着但太慢——网关等不到响应,先超时断开。间歇性出现说明不是配置写错,而是某类请求偶尔慢过了头:特定页面、特定时段、特定参数组合。把触发的那几个请求找出来,方向就清楚了一半。超时配置藏在三层,逐层对齐才能治本。
第一层:网关的超时
nginx 转发请求的等待上限由 proxy_read_timeout(反向代理场景)或 fastcgi_read_timeout(连 PHP 场景)控制,默认 60 秒。error.log 里出现 upstream timed out (110: Connection timed out) while reading response header,就是它触发的。调大数值能缓解,但只是把等待拉长,不是治病。同一段还有 proxy_connect_timeout 管建立连接的阶段,报错信息里写的是哪个参数,就调哪个。
第二层:应用的超时
PHP 里 max_execution_time 限制脚本执行时长,php-fpm 的 request_terminate_timeout 限制单个请求的总时长,谁先到谁生效,被掐断的那个请求对用户就是一次 504。跑批、导出报表这类长任务,要么单独调高限额,要么改成异步队列,别占着同步请求硬等。队列堆积还有一种表现:php-fpm 的 status 页里 active processes 长期等于上限,说明进程全忙,后来的在排队。
第三层:数据库的超时
慢查询和锁等待是间歇性 504 最常见的源头。一条 SQL 平时 200 毫秒,数据量涨上去之后偶尔跑 70 秒,网关 60 秒就断,于是"偶尔 504、刷新又好"。开启慢查询日志,long_query_time 设 1 秒,把慢 SQL 抓出来补索引。锁等待在 show processlist; 里表现为 Waiting for lock 状态,Time 列的秒数就是已经等了多久,配合 innodb_lock_wait_timeout(默认 50 秒)和 show engine innodb status 的锁信息,能定位到互相卡住的两条语句。补索引之后用 EXPLAIN 复查执行计划确实变了,别改完才发现优化器没走。
三层的关系要理顺:外层超时必须比内层宽,网关等的时间要长于应用,应用要长于数据库,次序反了会出现内层还在干活、外层已经放弃的浪费。正确顺序永远是先让后端快起来,再决定网关等多久。一味把 proxy_read_timeout 调到 300 秒,用户只会盯着转圈的页面更久。