FrankenPHP调参前后QPS变化需用wrk实测:固定-workers、max-requests、OPcache及HTTP模式,执行wrk -t4 -c100 -d30s并清空OPcache,避免冷启动与缓存干扰。

用 wrk 对比 FrankenPHP 调参前后的 QPS
FrankenPHP 的 QPS 变化对配置非常敏感,比如 worker 数量、max-requests、OPcache 是否启用、甚至 Caddy 的 HTTP/3 开关都会显著影响结果。直接看日志或 curl -I 没用,必须用压测工具实测。
-
wrk是最轻量也最贴近真实场景的选择:它默认复用连接、支持 HTTP/2 和 HTTP/3,和 FrankenPHP 的协议栈匹配度高 - 不要用
ab(Apache Bench),它不支持 HTTP/2+,且连接模型太“暴力”,容易把 FrankenPHP 的 worker 池打穿,测出来的是瓶颈而非真实吞吐 - 压测命令要带
-H "Accept: application/json"这类真实请求头,否则 FrankenPHP 可能走静态文件路径,绕过 PHP 执行逻辑
示例对比命令:
wrk -t4 -c100 -d30s http://localhost:8080/api/status其中
-t4 表示 4 个线程,-c100 表示维持 100 个并发连接,-d30s 表示持续 30 秒 —— 这个组合在中等负载下足够稳定,避免冷启动偏差
调参时必须固定的关键变量
QPS 对比失效,90% 是因为没锁住变量。FrankenPHP 启动后看似“就一个进程”,但背后涉及 Caddy 网络层、PHP worker 生命周期、OPcache 缓存命中率三重状态。
- 必须每次压测前清空 OPcache:
frankenphp php-cli -r "opcache_reset();",否则第二次压测会因缓存命中虚高 - 必须关闭开发模式下的文件监听(如 Laravel Octane 的
--watch):chokidar 会触发频繁 reload,干扰 worker 稳定性 - 必须用相同路由路径压测:不要用
/(可能命中 Caddy 静态服务),而要用明确走 PHP 的路径,比如/index.php或框架约定的/api/health - 必须禁用 HTTPS 重定向(如果只是本地对比):HTTP/3 + TLS 握手会引入额外抖动,先测纯 HTTP 再比 HTTPS
frankenphp php-server 启动参数直接影响 QPS 上限
FrankenPHP 不是“开箱即用就最快”,它的 php-server 子命令有几个关键参数,改一个就可能让 QPS 波动 ±30%:
立即学习“PHP免费学习笔记(深入)”;
-
--workers:指定常驻 PHP worker 进程数。设为 CPU 核心数 × 2 是常见起点,但超过 8 之后收益递减,还可能因内存竞争反而下降 -
--max-requests:每个 worker 处理多少请求后自动重启。设为 0(永不重启)短期 QPS 高,但长期有内存泄漏风险;设为 1000 是较稳妥的平衡点 -
--env:务必显式传--env=APP_ENV=production,否则 Laravel/Symfony 会加载调试组件,拖慢每个请求 20ms+ -
--log-level:压测时必须设为warn或error,info级别日志会同步刷盘,严重拖累吞吐
示例启动命令(用于压测):
frankenphp php-server -r public/ --workers=4 --max-requests=1000 --env=APP_ENV=production --log-level=warn
QPS 跳变时优先检查这三处
FrankenPHP 的 QPS 不像 Nginx+PHP-FPM 那样“稳如老狗”,它的常驻模型会让某些问题暴露得更早、更剧烈:
- 查看
frankenphp logs输出里有没有worker exited unexpectedly:说明某个 worker 崩溃了,Caddy 会临时降级到单 worker 模式,QPS 断崖下跌 - 用
ps aux | grep frankenphp观察实际 worker 进程数是否和--workers一致:有时因内存不足,Go runtime 会静默放弃拉起新 worker - 检查
/proc/<pid>/status</pid>中的VmRSS:单个 worker 内存超过 256MB 后,Linux OOM killer 可能介入,但不会报错,只会悄悄 kill 进程
真正难的不是跑出一个数字,而是让这个数字可复现、可归因。FrankenPHP 把 PHP-FPM 和 Web Server 合并了,但也把原来分散在两处的问题,全压缩进了一个进程里 —— 日志、内存、连接复用、协议协商,全都耦合在一起。调参不是调一个值,是在平衡整个运行时的呼吸节奏。



















