Worker模式下static变量持续增长是正常现象,因其位于常驻进程的顶层作用域,随请求累积且无自动重置;需区分合理计数与内存泄漏,避免误作跨请求缓存或忽略生命周期管理。

正常。但前提是这个 static 变量位于 Worker 脚本的顶层作用域(即非函数内、非类静态属性),且你明确依赖它跨请求累积。
为什么 static 在 Worker 模式下会持续增长
Worker 模式的核心是 PHP 进程常驻内存:一个 Worker 实例启动后,不会随每次 HTTP 请求结束而销毁,整个脚本生命周期远超单次请求。这意味着:
-
static变量在脚本首次加载时初始化,之后所有请求共享同一份内存副本 - 没有自动重置机制——除非你手动清零、或 Worker 因崩溃/主动重启被回收
- 这和传统 PHP-FPM 完全不同:FPM 每次请求都从头
include脚本,static实际上每次都是新实例
哪些 static 场景容易误判为“异常”
不是所有 static 增长都有意义,常见误导点:
- 在路由分发逻辑里用
static $counter = 0; $counter++;统计总请求数——这本身合理,但若你期望它按天/按小时归零,就得自己加时间判断或外部信号触发重置 - 把
static当作“全局缓存”却没做失效控制,比如static $cache = [];不断$cache[$key] = $value;,最终 OOM - 在类定义外写
static $config = require 'config.php';,看似省事,但配置变更后无法热更新,只能重启 Worker - 误以为
static是线程安全的——FrankenPHP 的每个 Worker 运行在独立线程中,static不跨线程共享,但单线程内多次请求会叠加
如何验证 static 行为是否符合预期
别只看数字变大,重点确认它是否真的“该变大”:
立即学习“PHP免费学习笔记(深入)”;
- 用
frankenphp_worker_status()查看当前 Worker 实例的运行时长和已处理请求数,和你的static计数器对比,两者应大致同频增长 - 检查 Worker 是否意外重启:查看日志里是否有
worker exited unexpectedly或restarting worker,如果有,计数器应出现跳变或归零 - 在 Worker 入口加
echo "PID: " . getmypid() . ", Uptime: " . (time() - $_SERVER['REQUEST_TIME_FLOAT']) . "\n";,确认你观测的是同一个进程实例 - 如果需要隔离计数(比如每分钟统计),不要依赖
static,改用apcu_store()配合 TTL,或外部 Redis
真正容易被忽略的不是 static 本身,而是忘记 Worker 模式彻底改变了 PHP 的生命周期假设——很多过去“安全”的写法,现在会悄悄积累状态、泄漏内存、或产生竞态。越简单的 static,越要问一句:这个值,到底该活多久?



















