frankenphp cpu 占用高主因是默认普通模式下频繁初始化框架及 opcache 配置不当;需调优 num_threads、禁用 opcache.save_comments、启用 worker 模式并确保初始化逻辑惰性加载。

FrankenPHP 启动后 PHP 进程 CPU 占用高,通常不是 FrankenPHP 本身有 bug,而是默认配置没对齐你的应用负载特征,尤其是 Laravel/Symfony 这类框架在常驻模式下容易暴露初始化开销和内存管理问题。直接调小 num_threads 或杀进程治标不治本,得从运行模型、OPcache 配置和 worker 生命周期三处下手。
为什么 FrankenPHP 的 PHP 线程会持续吃 CPU
FrankenPHP 默认启用普通模式(非 worker),每个请求都走完整 PHP 生命周期:加载框架、注册服务、解析配置、执行脚本、销毁对象。Laravel 启动一次常达 30–60ms,压测时大量并发请求排队等待线程,top 看起来就是一堆 frankenphp 进程在“空转”——实际是反复初始化+GC 压力大。
- 普通模式下,
num_threads设置过高(默认为 CPU 核数 ×2)会导致线程争抢,上下文切换频繁,CPU 利用率虚高 - 没开 OPcache 或配置不当(如
opcache.save_comments=1),每次请求都要重编译带注释的框架文件 - PHP 脚本里存在未释放的资源(如 PDO 预处理句柄、全局静态变量缓存),worker 模式下会累积泄漏
必须改的 Caddyfile 配置项
FrankenPHP 的 frankenphp 全局块直接控制 PHP 运行时行为,以下几项不配好,CPU 高的问题基本无解:
-
num_threads 4:中小项目设为 CPU 核数(别信默认 ×2),4 核机器设 4 即可;超过 8 核再考虑微调 -
php_ini opcache.enable 1和php_ini opcache.save_comments 0:后者对 Laravel/Symfony 是刚需,否则注释占满 opcache 内存,触发频繁重编译 -
php_ini opcache.interned_strings_buffer 16:若opcache_get_status()['interned_strings_usage']['used_memory']接近上限,必须加,否则字符串 intern 失败导致 CPU 暴增 - 确认没漏掉
php_ini memory_limit 256M:太低会频繁 GC,太高则 RSS 上升间接推高 CPU 调度压力
切到 worker 模式前要检查的三件事
worker 模式能让框架初始化只做一次,但前提是你的代码能扛住常驻生命周期。盲目开启反而让 CPU 更高:
- 确认入口脚本(
file指向的 PHP 文件)只做路由分发,不包含new App()或require vendor/autoload.php以外的初始化逻辑——这些该由框架自己在第一次请求时惰性加载 - 检查所有全局变量、静态属性是否会在多次请求间污染状态,尤其注意
$_SERVER、$_ENV、单例容器实例 - 禁用开发期扩展:如
xdebug、blackfire必须从镜像中移除,它们在常驻进程里会持续采样,CPU 直接翻倍
验证优化是否生效的两个命令
别只看 top,要盯真实指标:
- 查 OPcache 实际使用:
curl -s http://localhost:8080/health/opcache | jq '.memory_usage.used_memory'—— 理想值应稳定在总opcache.memory_consumption的 60–80%,长期低于 30% 说明没缓存到关键脚本 - 看线程实际负载:
ps -eLo pid,lwp,nlwp,comm | grep frankenphp | awk '{if($3>1) print $0}'—— 若nlwp(线程数)远高于num_threads,说明内部 fiber 或协程没受控,得检查是否有Fiber未正确start()或resume()
worker 模式下最易被忽略的是“第一次请求慢 + 后续极快”这个现象,如果每次请求都差不多慢,大概率是框架初始化逻辑被写进了 worker 启动脚本,而不是按需加载。这点不揪出来,调再久配置也没用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











