1. 为什么我们需要压测 PHP 系统?
作为一名 PHP 开发者,我经常遇到这样的困惑:明明本地开发环境跑得飞快的代码,一上线就各种性能问题。直到学会了用 wrk 进行系统压测,才真正掌握了性能优化的"指南针"。
压测不是高级架构师的专利,每个 PHP 开发者都应该掌握这项基础技能。它能帮我们:
- 发现系统真实的吞吐量瓶颈(是 CPU 算力不足?还是数据库查询太慢?)
- 评估代码改动对性能的影响(那个"优化"真的有效吗?)
- 预测系统在流量增长时的表现(双十一能扛住吗?)
2. 环境准备:搭建压测工作台
2.1 安装 wrk 压测工具
wrk 是我用过最轻量高效的 HTTP 压测工具,它用 C 语言编写,单机就能产生上万 QPS 的压力。安装方法因系统而异:
bash复制# MacOS (推荐Homebrew)
brew install wrk
# Ubuntu/Debian
sudo apt-get install wrk
# CentOS (需先安装EPEL仓库)
sudo yum install epel-release
sudo yum install wrk
提示:如果 yum 安装失败,可以源码编译:
bash复制git clone https://github.com/wg/wrk.git cd wrk && make sudo cp wrk /usr/local/bin/
2.2 准备测试环境
压测前需要确认:
- PHP 服务已启动(比如
php -S 127.0.0.1:8000) - 测试接口可正常访问(用 curl 或浏览器检查)
- 关闭开发环境的 Xdebug 等调试工具(它们会严重拖慢性能)
建议测试真实的业务接口,比如用户登录接口:
code复制http://127.0.0.1:8000/api/login
3. 执行你的第一次压测
3.1 基础压测命令
bash复制wrk -t2 -c100 -d30s http://127.0.0.1:8000/api/login
参数解析:
-t2:使用 2 个线程(建议设为 CPU 核心数)-c100:保持 100 个并发连接-d30s:持续压测 30 秒
3.2 理解压测报告
运行后会看到类似输出:
code复制Running 30s test @ http://127.0.0.1:8000/api/login
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 45.23ms 12.10ms 180.45ms 85.60%
Req/Sec 1.15k 80.50 1.30k 90.00%
68542 requests in 30.10s, 15.20MB read
Requests/sec: 2277.14
Transfer/sec: 516.54KB
Latency Distribution
50% 42.10ms
75% 50.20ms
90% 65.30ms
99% 120.50ms
关键指标解读:
- QPS (Requests/sec):2277.14 表示每秒处理 2277 个请求
- Latency (延迟):
- 平均延迟:45.23ms
- P99 延迟:120.50ms(99% 请求在 120ms 内完成)
- 吞吐量:30 秒共处理 68542 个请求
4. 系统资源监控技巧
4.1 实时监控 CPU 和内存
另开终端窗口运行:
bash复制# 基础监控
top
# 更直观的 htop(需先安装)
htop
观察重点:
- CPU:
us(用户态)高说明 PHP 代码消耗大,sy(系统态)高说明系统调用频繁 - 内存:关注是否触发 Swap 使用
- Load Average:超过 CPU 核数说明系统过载
4.2 PHP-FPM 专项监控
如果是 PHP-FPM 模式:
bash复制# 查看进程数
ps aux | grep php-fpm | wc -l
# 查看进程状态
sudo watch -n 1 "ps aux | grep php-fpm"
关键指标:
- 活跃进程数是否接近
pm.max_children - 单个进程的内存占用是否持续增长(可能存在内存泄漏)
5. 建立性能基线报告
将压测结果整理成表格,作为后续优化的基准:
| 指标项 | 测试结果 | 健康参考值 |
|---|---|---|
| QPS | 2277 req/s | 根据业务需求评估 |
| 平均延迟 | 45.23ms | < 200ms |
| P99 延迟 | 120.50ms | < 500ms |
| CPU 使用率 | 85% | < 70% 为佳 |
| 内存占用 | 1.2GB | 观察增长趋势 |
| 错误率 | 0% | 应始终为 0 |
6. 常见问题排查指南
6.1 QPS 低但 CPU 使用率不高
- 可能原因:数据库查询慢、外部 API 调用阻塞
- 解决方案:
- 检查 MySQL 慢查询日志
- 优化 SQL 查询,添加合适索引
- 对慢 API 调用添加缓存
6.2 高并发时连接被拒绝
- 可能原因:达到系统文件描述符限制
- 解决方案:
bash复制# 临时提高限制
ulimit -n 65535
# 永久生效(需修改 /etc/security/limits.conf)
* soft nofile 65535
* hard nofile 65535
6.3 P99 延迟远高于平均延迟
- 可能原因:偶发慢请求(GC、锁竞争、慢查询)
- 解决方案:
- 开启 PHP slowlog
- 检查是否有循环引用导致 GC 压力大
- 分析数据库锁情况
7. 进阶:自动化压测脚本
创建 benchmark.sh 自动化压测流程:
bash复制#!/bin/bash
URL="http://127.0.0.1:8000/api/login"
THREADS=2
CONNECTIONS=100
DURATION="30s"
echo "开始压测:$URL"
echo "线程数:$THREADS,并发数:$CONNECTIONS,持续时间:$DURATION"
echo "--------------------------------"
wrk -t$THREADS -c$CONNECTIONS -d$DURATION $URL
echo "--------------------------------"
echo "压测完成,请检查上方结果和系统监控数据"
使用方法:
bash复制chmod +x benchmark.sh
./benchmark.sh
8. 真实案例:我是如何优化登录接口的
最近我对一个用户登录接口进行了压测优化,过程很有代表性:
-
初始压测结果:
- QPS:320
- P99 延迟:890ms
- CPU 使用率:65%
-
问题定位:
- 发现每次登录都查询用户权限表
- 权限数据很少变化却频繁查询
-
优化方案:
- 将权限数据缓存到 Redis
- 设置 5 分钟过期时间
-
优化后结果:
- QPS:2100(提升 6.5 倍)
- P99 延迟:120ms
- CPU 使用率:45%
这个案例说明,简单的缓存策略就能带来显著的性能提升。关键在于通过压测找到真正的瓶颈点。