FrankenPHP滚动发布的核心是worker模式下通过frankenphp stop-workers命令触发旧worker优雅退出、新worker自动拉起,全程不中断请求;必须启用FRANKENPHP_WORKER=1、php_worker指向public/index.php绝对路径,并分步完成代码切换与worker通知。

FrankenPHP 滚动发布的核心不是“重启服务”,而是让新旧代码版本的 worker 实例交替退出、新 worker 自动拉起,全程不中断请求。关键在于 FRANKENPHP_WORKER=1 必须启用,且必须配合 frankenphp stop-workers 命令触发可控滚动,不能靠 kill 或信号重载。
必须开 worker 模式,否则根本谈不上滚动
普通模式(没设 FRANKENPHP_WORKER=1)下,FrankenPHP 启动即阻塞主进程,改代码后只能 kill 再启——必然中断所有连接。worker 模式才是滚动发布的前提:
-
FRANKENPHP_WORKER=1是环境变量,不是 CLI 参数;漏设会导致php_worker配置静默失效 - Caddyfile 中的
php_worker指令必须指向 Symfony/Laravel 的public/index.php绝对路径,例如/var/www/current/public/index.php - 路径写相对路径(如
./public/index.php)或错误路径会令 worker 启动失败,但无报错,只在日志里留一句 “failed to start worker”
发布流程必须分两步:换代码 + 通知 worker 退出
FrankenPHP 不监听 SIGHUP,也不支持 reload,滚动依赖的是 worker 生命周期管理机制:
- 先部署新代码到独立目录(如
/var/www/myapp/releases/20261010-150000),再用软链接ln -sf切换current - 确保新目录下
public/index.php可读、var/cache可写、已执行composer install --no-dev --optimize-autoloader - 执行
frankenphp stop-workers—— 它不会杀 Caddy 主进程,只向所有活跃 worker 发送“完成当前请求后退出”信号 - 新请求会自动由新 worker 处理(因
current已切换,public/index.php加载的是新代码)
max_requests 是滚动节奏的控制阀
单个 worker 处理请求数上限决定滚动频率,设得太小会频繁 fork,太大则新代码生效慢:
立即学习“PHP免费学习笔记(深入)”;
- 推荐设为
1000~5000,兼顾内存泄漏兜底与更新及时性 - FrankenPHP 达到
max_requests后自动 fork 新 worker,旧 worker 处理完手上请求再退出,天然支持平滑过渡 - 不要依赖 OPcache 自动失效:即使切了软链,旧字节码仍缓存在内存里,必须靠 worker 退出+新 worker 加载来刷新
最容易被忽略的一点是:frankenphp stop-workers 命令必须在 FrankenPHP 进程所在宿主机上执行,不能在另一个容器或远程 SSH 会话里调用——它通过 Unix socket 与本地 FrankenPHP 实例通信,路径默认为 /tmp/frankenphp.sock,跨环境调用会失败并报错 connection refused。



















