正常。static变量在Worker脚本顶层作用域持续增长是设计使然,因其随常驻进程复用内存、无自动重置;需通过frankenphp_worker_status()和PID/uptime验证是否与Worker生命周期一致,避免误作缓存或忽略TTL、热更新与竞态控制。

static变量在Worker里越加越大是正常现象
只要它位于Worker脚本的顶层作用域(即不在函数内、也不在类里),且你没手动重置,那每次请求都复用同一份内存——计数器变大、数组追加元素、连接对象复用,全都是设计使然,不是bug。关键要区分:这是你主动设计的跨请求状态,还是误把临时数据塞进了static导致污染。
怎么确认是不是真该积累
别只盯着数字涨了没,重点看它和Worker生命周期是否对齐:
- 调用
frankenphp_worker_status(),对比返回的uptime和requests_handled,和你的static计数器数值是否同频增长 - 在Worker入口加
echo "PID: " . getmypid() . ", uptime: " . (time() - $_SERVER['REQUEST_TIME_FLOAT']) . "\n";,连续curl几次,确认PID没变、uptime持续增加——否则你看到的“增长”可能只是Worker重启后的新实例 - 查日志有没有
worker exited unexpectedly或restarting worker,有则说明计数器跳变或归零是正常的
哪些static用法容易踩坑
看起来省事,实则埋雷:
-
static $cache = [];不断$cache[$key] = $value;却不设TTL或清理逻辑 → 内存缓慢上涨,最终OOM -
static $config = require 'config.php';→ 配置文件改了不生效,只能重启Worker - 在路由分发层用
static $total_requests = 0;统计,却期望它按小时清零 → 得自己加时间判断或监听信号 - 误以为
static线程安全 → 实际上FrankenPHP每个Worker是独立线程,static不跨线程共享,但单线程内多次请求会叠加,若没做同步控制,可能引发竞态
需要隔离计数时别硬扛static
如果目标是每分钟请求数、每用户会话计数、或带过期的缓存,static不是解法:
立即学习“PHP免费学习笔记(深入)”;
- 用
apcu_store('counter', $val, 60)配合TTL,比自己维护数组更轻量 - 跨Worker或需持久化的场景,直接上
Redis::incr('req:minute:' . date('YmdHi')) - 纯内存隔离且需高频读写?考虑
WeakMap或协程本地存储(如Swoole\Coroutine\Channel)
真正容易被忽略的,不是static本身,而是忘了Worker模式彻底改写了PHP的生命周期假设——过去“安全”的写法,现在会悄悄积累、泄漏、错乱。



















