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$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_read_timeout 120s; # 两次读取之间的空闲超时(默认 60s),不是整次请求上限
fastcgi_connect_timeout 10s; # 建连超时
fastcgi_send_timeout 60s; # 发送请求体超时
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
2. PHP-FPM 侧(pool 配置,如 www.conf)
request_terminate_timeout = 120s ; FPM 处理单次请求的终止限制
3. PHP 侧
max_execution_time = 120 ; PHP 执行计时,Unix 下通常不计系统调用等等待
三者计时范围不同,没有普适的大小排序。按接口预算、排队与依赖耗时设置,验证配置后按部署流程 reload/restart。
治本:找出慢的请求
# 开启 PHP-FPM 慢日志
# www.conf
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s
慢日志提供采样时的调用栈,可与同一时段的 MySQL 慢查询记录核对。应用已通过 OpenTelemetry 接入观测云时,再检查对应请求中已采集的数据库或外部请求 Span,比较各段耗时,确认下一步应优化哪项依赖。
这些情况别硬调超时
- 报表/导出类长任务:改为异步(投递队列+后台处理+轮询/通知结果),HTTP 长连接扛几分钟天然脆弱
- 整站性 504:不是个别接口慢而是 PHP-FPM 池打满(
pm.max_children太小或进程都被慢请求占住),看pm.status_path状态页 - 504 变 502:FPM 进程被杀掉重建时会变 502,两个错误常是同一根因
常见问题(FAQ)
Q:调大 timeout 后还是 504?
A:确认三层都改了且都 reload/restart;前面若还有 CDN/LB(需按所用 CDN/LB 产品与套餐核查限制),那一层先超时。
Q:如何只对个别接口放宽?
A:单独 location 块配该路径的 fastcgi_read_timeout,不必全局放宽。
Q:max_children 怎么估?
A:按真实负载下进程内存分布与可用预算估算,考虑共享页、其他进程和峰值;固定 20% 余量不能替代压测。