504 gateway timeout 根源在于 nginx、php-fpm 和宝塔三层超时配置未同步:需同时调高 fastcgi_read_timeout(nginx)、request_terminate_timeout(php-fpm)及宝塔“网站超时时间”,三者缺一不可,且必须一致并重启服务生效。

504 Gateway Timeout 不是 PHP 挂了,而是 Nginx 在等 PHP-FPM 响应时主动放弃了——关键得调对 proxy_read_timeout、fastcgi_read_timeout 和 request_terminate_timeout 这三处,漏一个都白调。
为什么只改 Nginx 的 proxy_read_timeout 还是 504?
Nginx 默认的 proxy_read_timeout 是 60 秒,但宝塔默认还启用了 FastCGI 协议直连 PHP-FPM,此时真正起作用的是 fastcgi_read_timeout(同样默认 60 秒)。如果你只在 server 块里加了 proxy_read_timeout 300,却没在 location ~ \.php$ 块里补上 fastcgi_read_timeout 300,Nginx 依然会在 60 秒后断连。
常见错误现象:
– 改完 proxy_* 参数重载 Nginx,请求仍卡在 60 秒返回 504
– curl -v 看响应头显示 X-Powered-By: PHP/8.0,说明 PHP 实际已启动,只是 Nginx 先撤了
- 必须在站点配置文件的
location ~ \.php(.*)$区块内,include fastcgi.conf之前添加: fastcgi_connect_timeout 300;fastcgi_send_timeout 300;fastcgi_read_timeout 300;- 别写在
server块顶层——那里对 FastCGI 请求不生效
PHP-FPM 的 request_terminate_timeout 必须 ≥ max_execution_time
PHP 脚本里设 set_time_limit(300) 或改 max_execution_time = 300 不够。PHP-FPM 进程层有个更硬的开关:request_terminate_timeout,它会直接 kill 掉超时的 worker。如果这个值是 60s,而你把 max_execution_time 改成 300,PHP 进程早在第 61 秒就被干掉,Nginx 自然收不到响应。
使用场景:
– 宝塔面板 → 「软件商店」→ 找到对应 PHP 版本 → 「设置」→ 「PHP-FPM 设置」→ 填入 request_terminate_timeout = 300s(注意带单位 s)
– 同时进「配置修改」选项卡,确认 max_execution_time = 300
OpenClaw Gateway 重启性能分析工具:分析重启速度、定位启动慢原因、生成性能报告、诊断启动问题。支持 Windows (PowerShell) 与 Linux (Bash)。触发场景:分析 gateway 重启、检查启动时间、生成报告、诊断异常。
-
request_terminate_timeout的值必须大于等于max_execution_time,建议两者设为相同值 - 改完必须点击「重启 PHP 服务」,不是「重载配置」——只有重启才能加载新的 FPM 配置
- 用
ps aux | grep php-fpm看进程启动时间是否更新,避免配置未生效
别忽略宝塔界面里那个隐藏的「网站超时时间」
宝塔在「网站」→ 对应站点 → 「网站目录」选项卡最底部,有个不起眼的输入框叫「网站超时时间」,默认填的是 60。这个值会强制覆盖 Nginx 配置里的所有超时指令,优先级最高。哪怕你上面三处全调成 300,这里还是 60,照样 504。
参数差异:
– 这个值单位是秒,不带单位,也不接受 ms
– 它对当前站点所有 PHP 请求生效,无法按路径细分
– 如果多个站点共用同一 PHP 版本,该值按最长需求设置
- 找到该输入框,改成和
fastcgi_read_timeout一致的值(如300) - 点「保存」后,务必手动点击右上角「重载配置」按钮
- 这个操作不会重启 PHP,所以不用重复「重启 PHP 服务」
调高超时只是兜底,真卡点往往不在 PHP 本身
如果你发现某个接口稳定在 299 秒才返回,或者每次 504 都发生在同一 URL(比如 /api/v1/export),别急着把所有 timeout 都拉到 1200。先看日志:
- 查 PHP 错误日志:
/www/wwwlogs/php_error.log,搜Maximum execution time exceeded—— 没这句,说明问题不在 PHP 脚本执行,而在下游(DB、API、文件 I/O) - 查 MySQL 慢查询:
tail -f /www/server/data/mysql-slow.log,看是否有未加索引的SELECT *卡住 - 用
strace -p $(pgrep -f "php-fpm: pool www") -e trace=connect,sendto,recvfrom抓网络调用,确认是卡在 curl 还是数据库连接
容易踩的坑:
– set_time_limit(0) 在 PHP-FPM 下完全无效,FPM 会无视它
– 把 fastcgi_read_timeout 设成 3600,结果数据库死锁,反而拖垮整个 PHP-FPM 池
– 异步任务(导出、转码)硬塞 Web 请求,应该用 shell_exec("nohup php /path/to/cli.php > /dev/null 2>&1 &") 或宝塔计划任务拆出去










