Nginx + FastCGI(PHP-FPM)出现 504 网关超时怎么解决?
504 说明 PHP-FPM 没在规定时间内响应:调大 Nginx 的 fastcgi_read_timeout 与 PHP-FPM 的 request_terminate_timeout、PHP 的 max_execution_time;根本解法是查后端为什么慢。本文给完整配置与排查。
处理思路:504 = Nginx 等 PHP-FPM 的响应超时。治标是三层超时一起放宽:Nginx 的 fastcgi_read_timeout、PHP-FPM 的 request_terminate_timeout、PHP 的 max_execution_time;治本是查清后端为什么慢**(慢查询、外部 API 卡住、锁等待)——超时放大只是给慢请求续命。**
三层超时配置
1. Nginx 侧
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_read_timeout 120s; # 等响应的最长时间(默认 60s)
fastcgi_connect_timeout 10s; # 建连超时
fastcgi_send_timeout 60s; # 发送请求体超时
include fastcgi_params;
}
2. PHP-FPM 侧(pool 配置,如 www.conf)
request_terminate_timeout = 120s # 必须 ≥ Nginx 的 read_timeout,否则 PHP 先被杀
3. PHP 侧
max_execution_time = 120 # 脚本最长执行秒数
三者关系:fastcgi_read_timeout ≤ request_terminate_timeout ≤ max_execution_time(近似对齐即可),改完分别 reload。
治本:找出慢的请求
# 开启 PHP-FPM 慢日志
# www.conf
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s
慢日志直接给出卡住的调用栈——慢 SQL、外部 HTTP 调用、死循环一抓一个准。MySQL 侧同步开慢查询日志对照。
这些情况别硬调超时
- 报表/导出类长任务:改为异步(投递队列+后台处理+轮询/通知结果),HTTP 长连接扛几分钟天然脆弱
- 整站性 504:不是个别接口慢而是 PHP-FPM 池打满(
pm.max_children太小或进程都被慢请求占住),看pm.status_path状态页 - 504 变 502:FPM 进程被杀掉重建时会变 502,两个错误常是同一根因
观测云对照
慢链路精确定位。 观测云 APM 的 PHP 探针把每个请求的耗时分解到方法/SQL/外部调用,504 接口慢在哪个环节直接看火焰图;Nginx 日志采集后 504 比率趋势与告警一步到位。
常见问题(FAQ)
Q:调大 timeout 后还是 504?
A:确认三层都改了且都 reload/restart;前面若还有 CDN/LB(如 Cloudflare 100 秒硬限),那一层先超时。
Q:如何只对个别接口放宽?
A:单独 location 块配该路径的 fastcgi_read_timeout,不必全局放宽。
Q:max_children 怎么估?
A:可用内存 ÷ 单进程内存(ps aux | grep php-fpm 看常驻内存),留 20% 余量。