swoole中全局变量跨请求共享,因worker进程常驻内存,static、global、$_server等不自动销毁,易致数据污染和内存泄漏;应改用协程本地存储(如context或coroutine\local)并显式清理。

全局变量在 Swoole 里是跨请求共享的
传统 PHP-FPM 中,$_GET、$_POST、$GLOBALS、static 变量甚至 global $foo 都只存活于单次请求生命周期内——请求结束,进程销毁,变量自动清空。而 Swoole 的 Worker 进程常驻内存,所有在 onWorkerStart 之后定义的全局变量(包括 static 属性、global 变量、未封装在函数内的顶层变量)会持续存在,被后续所有请求复用。
这意味着:你改了 $config['timeout'] = 30,下个请求看到的就是 30;你在某个 WebSocket 连接里给 static $counter++,下次任意请求进来时它已经不是 0 了。
常见错误现象:
- 用户 A 登录后把
$_SESSION模拟成全局数组$user_cache[$fd] = $uid,用户 B 请求时直接读到 A 的 uid - 数据库连接对象被赋给
global $pdo,但没做连接池或重连逻辑,第二个请求可能拿到已断开的句柄 - 日志计数器用
static $count = 0; $count++累加,结果每秒增长值远超实际请求数(因为协程并发写入未加锁)
协程间不共享局部作用域,但共享全局符号表
Swoole 协程是轻量级调度单元,每个 go(function() { ... }) 有独立的栈帧和局部变量,但它们运行在同一个 Worker 进程里,共用该进程的全局符号表。也就是说:use ($x) 传进协程的是副本,但直接访问 $global_var 或 self::$static_prop 拿到的是同一块内存。
使用场景提醒:
- 不要在协程里直接修改
global $cache,除非你明确做了mutex或Channel同步 -
static数组是高频泄漏点:比如static $log_buffer = [];只增不删,最终 OOM - 单例类如
Redis::getInstance()必须保证线程/协程安全——Swoole 下的“单例”本质是进程级单例,不是请求级
超全局变量($_SERVER、$_REQUEST)不可靠
Swoole 不走 FPM 的 PHP_RINIT_FUNCTION / PHP_RSHUTDOWN_FUNCTION 流程,所以 $_GET、$_POST、$_COOKIE 在 HTTP Server 或 WebSocket Server 中默认为空或不完整。你看到的 $_SERVER['REQUEST_URI'] 往往是启动时的初始值,不是当前请求数据。
正确做法是显式从回调参数中取值:
- HTTP:
function onRequest($request, $response) { $uri = $request->server['request_uri']; $post = $request->post; } - WebSocket:
function onMessage($server, $frame) { $fd = $frame->fd; $data = $frame->data; } - 别依赖
$_FILES—— Swoole 的$request->files是手动解析后的结构,且需开启http_parse_post配置
替代方案:用协程本地存储 + 显式传参
避免全局污染最直接的方式,是放弃“隐式共享”,转向“显式传递”。Swoole 提供了 Swoole\Coroutine::getUid() 和 Swoole\Coroutine\Channel,但更推荐业务层控制:
- 把请求上下文封装成对象,用
go(function() use ($ctx) { ... })显式传入 - 用
Swoole\Coroutine\WaitGroup管理并发子任务,而不是靠全局计数器 - 缓存类改用
Swoole\Coroutine\Channel做协程安全队列,容量设为合理值(如new Channel(1024)),避免pop()阻塞 - 必须用静态缓存时,加上清理钩子:
go(function() { defer(function() { static::$cache = []; }); ... });
真正难的不是写对第一行代码,而是记住:Swoole 里没有“请求结束就自动清理”这回事。每个 static、每个 global、每个未释放的资源句柄,都在默默等待被下一个请求误用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











