Nginx 504 与 PHP-FPM 超时链条
发布时间:2026-04-09 10:40       
更新时间:2026-04-09 20:03
504 和 502 只差一个词:502 是后端没给出响应,504 是后端收到了请求、但在时限内没干完活。PHP 站点这条链路上有三道闸,任何一道先触发,用户就看到超时——排查的核心是找出谁的最小。
一、三道闸分别在哪
- Nginx 侧:fastcgi_read_timeout,默认 60 秒,管等多久放弃 PHP-FPM。
- PHP-FPM 侧:request_terminate_timeout(在 www.conf 里),到时强杀工作进程。
- PHP 侧:max_execution_time(php.ini,默认 30),只计脚本自身的执行时间。
三者谁最小谁先触发,现象还不一样:Nginx 超时给 504;FPM 强杀常见 502 或白屏;PHP 自身超时报 Fatal error。看到 504,先盯第一道。
二、逐个调大
```
# nginx 站点配置
location ~ \.php$ {
fastcgi_read_timeout 300;
fastcgi_connect_timeout 5s;
fastcgi_send_timeout 300;
}
# /etc/php-fpm.d/www.conf
request_terminate_timeout = 300s
# php.ini
max_execution_time = 300
```
改完 nginx -s reload 加 systemctl reload php-fpm。注意三处要一起核对:只改 Nginx 而 FPM 还是 30 秒杀进程,问题只会从 504 变成 502,换一种报错继续折磨你。改动前把当前值抄一份留档,超时是全局参数,调大影响所有站点,需要差异时按站点单独覆盖。如果链路前面还有负载均衡或 CDN,它的读超时就是第四道闸——任何一处小于后端处理时间,都会先断在那里。
三、先确认该不该等
导出报表、批量处理确实需要几分钟,调大合理。但多数 504 的根因是慢 SQL、外部接口卡死这类病态慢请求,把超时从 60 调到 600,只是把报错换成用户挂机。正确姿势是先定位:开启慢日志:
```
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
```
日志会直接打印卡在哪个函数哪一行。顺带说一个容易浪费时间的坑:max_execution_time 在命令行模式下默认不限制,所以命令行跑得动的脚本网页上跑不动,别在这一点上反复怀疑环境。
四、长任务的正确解法
分钟级的批量任务,通行做法是异步化:接口立即返回任务 ID,后台队列处理,前端轮询进度。超时参数调大只是止血,异步化才是治本。
排查顺序小结:error.log 看是不是 timed out,慢日志看卡在哪一行,再决定是调参数还是改任务形态。参数改完用一条确实慢的接口实测,别凭 reload 成功就默认生效。