frankenphp worker模式与fpm的根本差别在于运行时是否跨请求复用:fpm每次请求都完整初始化并销毁php进程,worker则常驻内存,复用框架、配置、连接及opcache,显著降低启动开销、提升并发密度并改变资源管理逻辑。

FrankenPHP Worker模式和FPM的并发模型差在哪
根本差别不在“能不能并发”,而在于并发单位是否跨请求复用运行时状态。FPM是“每个请求一个全新PHP进程”,FrankenPHP Worker是“一个PHP进程持续处理多个请求,且框架、配置、连接都常驻”。这直接导致启动开销、内存行为、连接复用能力完全不同。
Worker模式下PHP进程不销毁,FPM每次都要重初始化
FPM每个请求都走完整生命周期:fork → 加载扩展 → 初始化Zend引擎 → require_once所有类 → 解析配置 → 实例化容器 → 执行控制器 → exit释放全部内存。哪怕只是echo 'OK',Laravel也要花30–60ms做引导。
FrankenPHP Worker模式只在启动时执行一次上述流程,后续所有请求都复用已加载的类、已注册的服务、已初始化的PDO/Redis连接。你看到的frankenphp worker命令背后,是一个长期存活的Go协程调度PHP协程,不是反复拉起新进程。
- FPM里
$_SERVER每次都是全新生成;Worker里$_SERVER默认沿用上个请求(需手动重置或用frankenphp_clear_globals()) - FPM中
new PDO()每次新建连接;Worker中可复用同一实例(但要注意连接状态,如断连需重试) - FPM依赖
opcache.enable_cli=1对CLI无效;Worker模式本质就是CLI环境,opcache全程生效
FPM靠多进程实现并发,Worker靠协程+单进程实现高密度并发
FPM并发上限由pm.max_children硬限制,每个子进程独占几十MB内存,100个worker轻松吃掉3–4GB RAM;而FrankenPHP Worker默认只启1个PHP工作进程(可通过FRANKENPHP_WORKERS环境变量扩到N个),每个进程内用协程跑数百请求,内存增长平缓。
这意味着:FPM在200并发时可能已OOM,FrankenPHP Worker在相同机器上跑500并发仍稳定——不是因为“更快”,而是因为“不重复造轮子”。
- FPM进程间完全隔离,无法共享缓存或连接;Worker进程内协程可安全共用
static变量、全局连接池 - FPM对慢SQL敏感:一个阻塞查询拖垮整个worker;Worker中可用
Swoole\Coroutine\MySQL等异步驱动(需适配),避免阻塞 - FPM日志分散在access/error/slow log三处;Worker日志统一由FrankenPHP的
caddy模块输出,格式一致
配置和调试方式彻底不同,别套用FPM经验
你不能再查/var/log/php-fpm/www-error.log,FrankenPHP所有错误都打到标准输出或caddy日志文件(默认./logs/access.log);也不能用php-fpm -t验证配置,FrankenPHP用frankenphp run --config=Caddyfile启动即校验。
最易踩的坑是:把FPM的fastcgi_param写法照搬进FrankenPHP的Caddyfile,比如加fastcgi_param SCRIPT_FILENAME——它根本不认这个,FrankenPHP自动推导路径,强行覆盖反而导致SCRIPT_NAME错乱,返回404。
- 不要在Worker模式下用
register_shutdown_function()清理资源,它可能在下一个请求开始后才触发 - 别依赖
__destruct()释放数据库连接,协程切换不保证析构时机;显式调用$pdo = null或用连接池管理 - 启用Worker模式后,
opcache.revalidate_freq=0必须设为0,否则修改代码不生效(FPM里设成2即可)
真正难的不是切换命令,而是接受“PHP代码不再随请求生灭”这个前提——所有状态管理逻辑都要重审。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











