本文目录导读:

分析 PHP 慢日志的核心目的是找出执行时间过长的请求或函数调用,从而定位性能瓶颈,通常有两种情况:一种是 FPM 慢日志(记录了哪个 PHP 文件慢),另一种是 Xdebug/Blackfire 等性能分析工具(记录函数调用堆栈)。
以下以最常用的 PHP-FPM 慢日志(slowlog) 为例,提供系统化的分析方法:
确认慢日志是否开启及日志位置
-
检查配置文件(通常在
php-fpm.conf或www.conf中):# 开启慢日志 request_slowlog_timeout = 2s # 超过2秒的请求会被记录(可设1s、5s等) slowlog = /var/log/php-fpm/www-slow.log # 日志文件路径
-
查看日志位置:
- 默认路径:
/var/log/php-fpm/slow.log或/var/log/php/slow.log - 如果找不到,执行:
php -i | grep slowlog或grep -r "slowlog" /etc/php*
- 默认路径:
查看慢日志原始内容
-
基本查看命令:
tail -n 100 /var/log/php-fpm/slow.log
-
典型日志条目结构:
[21-Mar-2025 10:30:15] [pool www] pid 12345 script_filename = /var/www/html/index.php [0x00007f8a8c00d000] curl_exec() /var/www/html/api.php:205 [0x00007f8a8c00b000] get_remote_data() /var/www/html/api.php:180 [0x00007f8a8c008000] process_request() /var/www/html/index.php:45关键信息解读:
- 时间戳:看是否集中在特定时间段(比如数据库高峰、定时任务)。
- script_filename:慢请求的入口文件(
index.php)。 - 堆栈跟踪:从下往上看,最下面的最外层入口,最上面的是最终卡住的函数。重点关注
curl_exec、file_get_contents、mysql_query等耗时的 I/O 或数据库调用。
核心分析方法(三步走)
统计最多的“脚本文件”
看哪些页面/接口最慢:
# 统计慢日志中出现最多的前10个脚本文件 grep "script_filename" /var/log/php-fpm/slow.log | sort | uniq -c | sort -nr | head -10
出现: api.php 出现100次以上,则说明该接口需要优化。
分析具体的“慢函数”模式
频繁出现这些函数,通常意味着:
curl_exec/file_get_contents: 外部HTTP请求或API调用超时(最多见)。mysql_query/PDO::query: 数据库SQL慢查询(需联合MySQL慢日志看)。session_start(): 会话文件锁冲突(高并发时常见)。file_put_contents/fwrite: 磁盘IO问题或日志写入阻塞。sleep()/usleep(): 代码中主动休眠。
技巧: 如果看不懂堆栈中的PHP函数,很可能是使用了ORM框架(如Laravel、ThinkPHP) 的底层调用,此时需关注堆栈中的业务层函数名称(如
getUserList、orderPay)。
关联上下文找“罪魁祸首”
- 请求参数: 慢日志默认不记录GET/POST参数,如果发现是某个接口慢,需在业务代码中临时加日志记录参数。
/index.php?page=1000可能因为分页过大导致查询慢。 - 时间波动: 如果某天突然慢请求增多,对比日志时间,检查是否上线了新代码,或数据库数据量/连接数是否突增。
不同场景的优化建议
| 慢日志典型堆栈 | 大概率原因 | 针对性排查命令/工具 |
|---|---|---|
curl_exec 卡住 |
外部 API 超时、DNS 解析慢 | 设置 CURLOPT_TIMEOUT,用 curl -w 测试外部 URL |
PDO::query 卡住 |
SQL 全表扫描、无索引、死锁 | 开启 MySQL 慢查询日志,EXPLAIN 分析 SQL |
fwrite 卡住 |
日志文件写入频繁、磁盘 IO 高 | iostat -x 1 看 await 列,检查 log 目录是否 RAID 或网络盘 |
sleep() 出现 |
代码中人为设置了 sleep(常见于轮询) |
建议改用队列或定时任务 |
频繁出现 include/require |
文件系统慢(NFS挂载、Windows共享) | 改用 OPcache、使用本机磁盘 |
| 函数调用很深,全是框架核心代码 | 框架自身慢(如路由解析、依赖注入) | 开启 OPcache、考虑使用单元测试隔离慢分支 |
进阶:实时监控与分析
如果服务器很多,可以用工具自动化分析:
-
监控工具(实时):
# 实时观察慢日志(类似tail -f) tail -f /var/log/php-fpm/slow.log | awk '{print $0}' -
脚本分析(按分钟统计):
# 统计每分钟慢日志次数 awk '/^\[/{date=$1} /script_filename/{print date}' slow.log | sort | uniq -c -
工具推荐(生产环境):
- 阿里云ARMS / 日志服务:自动解析慢日志并生成报表。
- 开源的
php-fpm-slow-log-parser(Github上有):php-fpm-slow-log-parser.py -f slow.log --top=10 --by-script。 - 结合
strace(临时排查):如果慢日志说卡在curl,用strace -p PID看是否卡在connect或recv。
总结一句话:
看 script_filename 知道哪个文件慢,看 curl_exec / PDO::query 知道为何而慢,然后对症下药(优化SQL、设置超时、加缓存)。 大多数慢日志问题,最终都归结为外部请求超时或数据库查询过慢。