php-fpm慢日志是定位延迟执行代码(如sleep、i/o阻塞)最有效方式,配置slowlog和request_slowlog_timeout后可精确记录超时调用栈,直指问题行号。

PHP 中的延迟执行代码(如 sleep()、usleep()、time_nanosleep(),或隐式阻塞操作如同步数据库查询、文件锁、远程 API 调用)是导致响应变慢的常见原因。这类操作本身不报错,却会让请求卡住数秒,用户感知为“接口卡死”,而日志里可能只显示一条超时记录,根源难寻。
最有效、低侵入、生产就绪的监控方式,是启用 PHP-FPM 慢日志(slowlog)。
✅ 直接定位 sleep 类阻塞操作
PHP-FPM 原生支持在请求执行时间超过阈值时,自动记录完整调用栈,精确到哪一行调用了 sleep() 或陷入 I/O 等待。
- 编辑你的 Pool 配置(如
/etc/php/8.2/fpm/pool.d/www.conf):slowlog = /var/log/php-fpm/slow.log request_slowlog_timeout = 3s
- 确保
/var/log/php-fpm/目录存在且www-data(或对应运行用户)有写权限。 - 重启 PHP-FPM:
sudo systemctl reload php8.2-fpm
当某请求因 sleep(4) 卡住,slow.log 会输出类似内容:
[17-Aug-2026 10:35:22] [pool www] pid 9876 script_filename = /var/www/app/api.php [0x00007f1a2b3c4d50] sleep() /var/www/app/helpers/Debug.php:33 [0x00007f1a2b3c4e60] handleRequest() /var/www/app/api.php:12
→ 一眼锁定 Debug.php 第 33 行的 sleep(),无需 grep、无需复现。
? 辅助手段:识别非 sleep 类延迟源头
慢日志能捕获“耗时长”,但不区分是 CPU 密集还是 I/O 阻塞。可搭配以下方法交叉验证:
检查 PHP 错误日志 + access.log
对比access.log中request_time字段(Nginx 提供)与 slowlog 时间戳,确认是否真为脚本执行慢,而非网络或前端问题。-
用
strace追踪系统调用(临时诊断)
找到卡住的 worker 进程 PID,执行:sudo strace -p 9876 -e trace=nanosleep,select,poll,read,write -T
可直观看到进程是否卡在
nanosleep()、poll()(等待 socket)等系统调用上。 开启 OPcache 状态监控
若延迟伴随大量.php文件重复编译,说明 OPcache 未生效或配置不合理。访问opcache_get_status()查看opcache.hit_rate是否偏低。
⚠️ 注意绕过陷阱
- 不要依赖
grep -r "sleep" .—— 动态拼接函数名(如$func = 'slee'.'p'; $func(2);)、反射调用、或第三方 SDK 内部的阻塞逻辑,都会漏掉。 - 避免对导出、批量任务等合法长耗时脚本开启 slowlog,可单独为其配置
request_slowlog_timeout = 0(禁用)或提高阈值。 - 慢日志需配合 logrotate,防止磁盘占满;例如配置每日轮转、保留 7 天。
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











