ThinkPHP压测失真主因是未关闭调试模式、日志写盘、模板编译等开关,以及权限校验未缓存、路由未预加载、数据库连接未持久化;需关闭APP_DEBUG、启用路由缓存、添加PDO持久连接、优化RBAC索引并配置Swoole session。

APP_DEBUG 必须关掉,否则压测结果完全失真——日志写文件、模板实时编译、Trace 页面注入会把单请求耗时拉高 3–5 倍,QPS 看似只有几十,实际是配置拖垮的。
ab 命令快速基线测试
适合验证单接口吞吐能力,不依赖 GUI,能快速暴露配置级瓶颈。
-
ab -n 1000 -c 100 http://127.0.0.1/api/user/list:观察Requests per second和Time per request(尤其 P95) - POST 接口加
-p post_data.txt -T application/json,注意post_data.txt末尾不能有多余换行,否则 TP 解析失败报400 Bad Request - 加
-k测试长连接表现,TP6 默认支持 Keep-Alive,但 Nginx 需确认keepalive_timeout≥ 60 - 错误率突增且伴随
502 Bad Gateway,大概率是 PHP-FPMpm.max_children打满,不是 TP 问题
JMeter 模拟真实业务链路
TP 应用压测失真的主因,往往是 JMeter 请求不符合框架预期,而非代码本身慢。
- HTTP Header Manager 中必须显式添加:
X-Requested-With: XMLHttpRequest,否则部分中间件(如跨域或 AJAX 校验)会拦截并返回空响应或 500 - Content-Type 是
application/json时,TP6 要求 POST body 是合法 JSON 字符串,不能是{name=xxx}这种 form-style;JMeter 用JSON Extractor提取 token 后,记得在下个请求 Header 加Authorization: Bearer xxx - CSV Data Set Config 读取用户数据时,路径要填相对路径(如
users.csv),且文件编码为 UTF-8 无 BOM,否则input('user_id')可能解析为空 - 聚合报告里出现大量
Non HTTP response code: java.net.SocketException,说明后端连接被主动断开,优先检查 MySQLwait_timeout是否过短(建议 ≥ 300)
数据库连接池打满的典型表现与修复
压到 200+ 并发就报 SQLSTATE[HY000] [1040] Too many connections,这不是 MySQL 配置低,而是 TP 每次请求新建 PDO 连接没释放。
- 在
config/database.php的连接配置中加入:'params' => [PDO::ATTR_PERSISTENT => true],开启持久连接 - 确认 PHP-FPM 是
static或dynamic模式(非ondemand),否则子进程生命周期太短,持久连接无法复用 - MySQL 侧同步调大:
max_connections = 500,并设wait_timeout = 300,避免连接被服务端强制回收 - 别在控制器里手动调用
Db::connect()->close(),PDO 持久化由 PHP 自动管理;仅在 CLI 场景才需显式关闭
权限校验和路由预加载是高频接口的隐形杀手
列表页、搜索页这类接口压测 QPS 上不去,90% 情况下卡在权限中间件或路由解析,而不是 SQL。
立即学习“PHP免费学习笔记(深入)”;
-
Auth::check()在每次请求都查think_auth_access表?立刻改掉——缓存规则树,键名用auth_rules_{$uid},失效时间设为 600 秒 - 确认
route_cache已开启:php think route:build生成缓存,否则每请求都 parse 路由定义文件,CPU 白耗 - RBAC 表缺失索引会导致并发查询锁表:
think_auth_access必须有(uid, role_id)联合唯一索引;think_auth_rule的path字段加前缀索引:ADD INDEX idx_path (path(60)) - Swoole 环境下 session 默认关闭,
session('user_id')永远为 null,权限直接跳过——启动服务时加配置'session_on' => true,并用$request->header('token')替代input('token')



















