swoole内存泄漏主因是静态变量、闭包引用和资源未释放,需避免全局数据存储、解耦循环引用、协程后清理资源,并设置worker最大请求重启机制,结合监控工具定期分析内存使用。

直接说结论:Swoole不是“会用就行”的扩展,只要在onRequest里写个echo "hello"就以为掌握了,大概率会在Worker内存泄漏、协程状态污染、TaskWorker误用这三类问题上翻车。
为什么 global / static 变量在 onRequest 里会持续累加
因为Swoole Worker进程常驻内存,PHP脚本只加载一次,global $counter = 0或static $i = 0不会随每次请求重置——这和PHP-FPM有本质区别。
- 现象:两次HTTP请求返回的计数值是 1 → 2,而不是每次都从0开始
- 根本原因:Worker进程生命周期远长于单次请求,变量作用域跨请求存活
- 错误解法:试图用
unset($counter)在onRequest末尾清理——无效,下次请求进来又复用同一作用域 - 正确解法:用
Swoole\Table存共享状态,或用Swoole\Atomic做原子计数;若只是请求内临时状态,改用函数局部变量
task_worker_num > 0 却没触发 onTask 回调的常见原因
onTask不执行,往往不是配置没生效,而是任务根本没投递成功,或投递后被静默丢弃。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 检查
$server->task()返回值:返回false说明任务队列已满(默认队列长度16),需调大task_max_request或task_worker_num - 确认
task_worker_num在Server->set()中设置,且大于0;仅写task_enable_coroutine => true不启用TaskWorker - 注意:投递任务必须在Worker进程中(如
onRequest),不能在Master或Manager进程上下文中调用 - 调试技巧:在
onTask开头加var_dump(getmypid(), $data),确认回调是否进入、PID是否为TaskWorker进程
协程 HTTP 客户端报错 “Connection reset by peer” 的真实原因
这不是网络抖动,大概率是连接池管理失当或协程上下文错乱导致底层socket被提前关闭。
- 典型诱因:复用同一个
Swoole\Coroutine\Http\Client实例并发发起多个请求——协程客户端非线程安全,必须“一请求一实例”或严格串行使用 - 更隐蔽的问题:在协程中混用
file_get_contents()等未Hook函数,触发隐式同步阻塞,导致协程调度异常,进而影响后续HTTP连接状态 - 验证方式:把
go(function () { ... })换成Swoole\Coroutine\run()包裹整个逻辑,观察错误是否收敛——若收敛,说明原协程启动方式有嵌套或生命周期错位 - 生产建议:强制走连接池,且每个请求从池中取新实例,用完立即
$client->close()归还,避免keep_alive超时引发的RST
最易被忽略的是:Swoole的协程Hook有明确边界,sleep()、curl_exec()、mysqli_query()这些函数,不换用对应的协程版本,就会让整个协程挂起——表面看是慢,实则是阻塞了整个Worker。










