worker启动时必须在循环外初始化框架核心对象:vendor/autoload.php、应用内核(如kernel)、服务容器、数据库连接等仅执行一次,否则退化为传统fpm模式;请求处理逻辑须置于frankenphp_handle_request()回调内,并手动清理资源。

Worker启动时必须在循环外初始化框架核心对象
FrankenPHP Worker 模式下,进程常驻,vendor/autoload.php、应用内核(如 Kernel)、服务容器、数据库连接等**只能初始化一次**。若放到请求循环内,就等于退化成传统 FPM,完全失去常驻优势。
-
require_once __DIR__.'/../vendor/autoload.php':必须在while (frankenphp_handle_request())外执行,确保 OPcache 和类映射只加载一次 - 应用内核实例(如 Laravel 的
$kernel = new Kernel(...)或 Symfony 的$kernel = new Kernel(...)):需调用$kernel->boot()完成服务注册和配置解析 - 数据库连接池(如 PDO 实例或 ORM 连接管理器):可复用,但必须禁用持久连接(
PDO::ATTR_PERSISTENT => false),避免事务残留 - 缓存客户端(Redis/Memcached 实例):连接可复用,但不要在初始化阶段执行
set()或get()—— 那是请求级行为
不能在启动期初始化的用户态状态
任何与具体 HTTP 请求强绑定的数据,都严禁放在循环外初始化。否则会跨请求污染,比如 session 内容、用户权限、路由参数、中间件上下文等。
-
$_SERVER['REQUEST_URI']、$_GET、$_POST:由 FrankenPHP 在每次请求前重置,你无需也不该预设 - 框架的
Request对象:必须在frankenphp_handle_request()回调内通过Request::capture()或类似方式构造 - 静态缓存变量(如
static $userCache = []):会在 worker 生命周期内持续存在,下次请求直接读到上一次的数据 - 全局单例中存储的请求 ID、trace ID、认证 token:必须在每次请求开始时重新注入或生成
环境变量和配置必须提前注入,不依赖 .env 动态加载
独立二进制或 Docker 环境中,.env 文件通常不可读或只在启动时生效一次。Worker 进程不会重复执行 Dotenv::createUnsafeImmutable()->load(),所以 APP_ENV、APP_DEBUG 等必须作为系统环境变量传入。
- Linux 命令行启动时:用
APP_ENV=prod APP_DEBUG=0 ./frankenphp-worker --script /app/public/worker.php --addr :8080 - Docker 中:通过
environment:显式声明,而非挂载.env文件 - 宝塔面板:在站点设置 → 环境变量中添加,不是写在 PHP 配置文件里
- 切勿在
worker.php开头调用Dotenv::createUnsafeImmutable()->load()—— 它只会生效第一次,后续请求读不到更新后的值
初始化后必须验证是否真正复用,而不是“看起来像”
代码结构对不等于运行时生效。常见假象是:入口文件拆了循环,但实际每次请求仍触发完整 bootstrap 流程(比如 autoloader 被重复注册、Kernel::boot() 被反复调用)。
- 在
bootstrap/app.php开头加file_put_contents('/tmp/kernel_boot.log', getmypid().' '.date('H:i:s')."\n", FILE_APPEND);,观察日志是否只出现一次 PID - 用
get_class_vars()或debug_print_backtrace()检查Kernel实例是否被多次构造 - 连续发两个请求,在控制器里打印
getmypid(),确认 PID 相同;再查opcache_get_status()['opcache_hit_rate'],应明显高于 FPM 模式 - 如果发现
Class not found或Connection refused在第二次请求才报,大概率是初始化没成功或路径加载错位
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











