本文目录导读:

在PHP项目中定位慢日志和性能瓶颈,可以按照从宏观到微观的顺序进行排查。
下面是一套完整的排查流程、常用工具和命令。
第一步:开启与查看慢日志
这是最直接的第一步,它可以告诉你哪些请求慢以及卡在哪个环节。
PHP-FPM 慢日志(重点排查)
如果你的项目使用 Nginx + PHP-FPM,这是最常用的方式。
- 开启配置:在
php-fpm.conf或/etc/php/8.x/fpm/pool.d/www.conf中。 - 关键参数:
request_slowlog_timeout = 5s(执行超过5秒的请求记录)slowlog = /var/log/php-fpm-slow.log(日志路径)
- 使用方法:修改后重启 FPM:
sudo systemctl reload php-fpm
- 日志分析(重点看堆栈):慢日志不仅告诉你哪个URL慢,还会打印出函数调用堆栈,这是定位瓶颈的关键。
[22-Jun-2023 10:00:00] [pool www] pid 1234 script_filename = /var/www/html/public/index.php [0x00007f...] () /var/www/html/vendor/symfony/... 第100行 [0x00007f...] SomeFunction() /var/www/html/app/... 第50行 [0x00007f...] DatabaseQuery() /var/www/html/app/... 第20行如果看到堆栈停留在
curl_exec或file_get_contents,说明是外部HTTP请求慢;如果停留在mysqli_query或PDO->query,说明是数据库慢。
Nginx 访问日志(辅助)
用于统计哪些URI平均响应时间最长。
- 修改
nginx.conf中的log_format,加入请求耗时$request_time和上游耗时$upstream_response_time。log_format main '$remote_addr - $request_time - $upstream_response_time - "$request"';
- 分析:
awk '{print $7, $10}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
第二步:定位代码瓶颈(Profile分析)
慢日志只能告诉你大致的堆栈,但要找具体的函数耗时,需要使用 Profiler。
推荐工具:Xdebug + Qcachegrind
- 安装:
pecl install xdebug
- 配置(
php.ini):xdebug.mode=profile xdebug.output_dir=/tmp/xdebug xdebug.start_with_request=trigger
- 使用:访问
http://your-site.com/?XDEBUG_PROFILE,会在/tmp/xdebug生成文件。 - 分析:用
Qcachegrind(Linux/Mac)或WinCacheGrind(Windows)打开文件,你会看到瀑布图,一眼就能看出哪个函数独占时间最长(通常是self时间高)。
轻量级方案:Tideways / OneAPM / 阿里云ARMS
如果不想折腾,建议直接使用SaaS服务,它们自动标记慢事务、SQL慢查询、外部调用延迟,开箱即用。
第三步:最常见的三大瓶颈(深入分析)
大多数慢请求逃不出这3个原因,请重点排查:
数据库慢查询(占比最高)
- 开启 MySQL 慢日志:
SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- 超过1秒记录 SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
- 分析工具:
mysqldumpslow -s at /var/log/mysql/mysql-slow.log - 重点检查:
- 是否命中索引:用
EXPLAIN SELECT ...查看type是否为const/ref,rows是否很大。 - N+1查询问题(ORM最常见) :如果使用了 Laravel 或 ThinkPHP,查看是否有循环里查询数据库,如果有,使用
with()预加载。
- 是否命中索引:用
外部API调用(Redis / HTTP / 第三方接口)
- 排查方法:在代码中记录每次调用时间,或者利用 Xdebug Profile 查看时间消耗在
curl_exec上。 - 解决方案:
- 加超时:
curl_setopt($ch, CURLOPT_TIMEOUT, 3),如果第三方服务挂了,你的进程会卡住直到超时,设置短超时至关重要。 - 并发变串行:如果你调用了3个互相独立的API,总共耗时就是3个时间相加,改成并发请求(
curl_multi_exec或 Swoole)可大幅提升速度。
- 加超时:
内存耗尽 / 垃圾回收(GC)问题
- 排查:如果系统负载不高,但进程GC频繁,检查是否有大数组导致内存占用高。
- 命令:在业务代码里临时插入:
file_put_contents('/tmp/memory.txt', memory_get_peak_usage(true));
第四步:环境级瓶颈(基础设施)
如果代码优化后仍慢,检查以下环境指标:
- CPU与IO:使用
top或htop查看%wa(IO等待),如果IO等待高,多半是磁盘读写慢(例如日志写入或文件缓存)。 - Redis 命中率:如果用了 Redis 做缓存,但命中率很低,导致大量请求穿透到数据库,使用
redis-cli info stats查看keyspace_hits和keyspace_misses。 - PHP OpCache:
- 确认已开启:
php -i | grep opcache.enable - 如果没开启,PHP每次都需要解析编译代码,CPU开销极大。
- 确认已开启:
第五步:现代PHP异步化(进阶)
如果使用传统 FPM(每个请求一个进程,慢请求会占满进程导致队列堵塞):
- 痛点:某个接口很慢(如导出Excel),会占满所有PHP-FPM进程,导致其他请求排队。
- 解决方案:如果业务合适,可以引入 Swoole 或 Workerman,将常驻内存与协程结合,瓶颈定位方式也会从“加机器”变为“看协程调度”。
定位排查命令速查表
| 问题描述 | 执行命令 | 期望结果 |
|---|---|---|
| 请求超时 | tail -f /var/log/php-fpm-slow.log |
看到堆栈,确定是DB还是API |
| 单条SQL慢 | tail -f /var/log/mysql/mysql-slow.log |
找到慢SQL,执行 EXPLAIN |
| 平均响应慢 | ab -n 1000 -c 50 http://test.com/login |
查看平均时间,对比优化前后 |
| CPU 100% | top -Hp <php-fpm-pid> |
确认是CPU密集(算法)还是IO密集(等待) |
| 内存溢出 | grep 'Allowed memory' error.log |
增加 memory_limit 或优化代码 |
建议的排查顺序永远是: 网络/负载 → PHP-FPM慢日志 → 数据库慢日志 → Xdebug Profile 代码剖析 → 优化外部API/IO。 遵循这个顺序,基本能定位90%的PHP项目性能问题。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播