Coroutine::stats() 返回当前 Worker 进程内协程聚合状态,含 coroutine_num(活跃数)、coroutine_peak_num(历史峰值)、coroutine_last_id(最后 ID)、coroutine_stack_size(栈大小配置)。

Coroutine::stats() 返回什么数据
Coroutine::stats() 是 Swoole 提供的协程运行时统计函数,它不返回协程列表或 ID,只返回一个关联数组,包含当前 worker 进程内所有协程的聚合状态。关键字段有:coroutine_num(当前活跃协程数)、coroutine_peak_num(历史峰值)、coroutine_last_id(最后创建的协程 ID)、coroutine_stack_size(当前栈大小配置值)。
为什么 stats() 的 coroutine_num 不等于并发请求数
常见误解是把 coroutine_num 当作“当前正在处理的请求量”,但它实际反映的是尚未结束的协程总数——包括:
• 正在执行 I/O 操作(如 $client->recv())并挂起等待响应的协程
• 因 co::sleep() 或未设 timeout 的 cURL 阻塞而长期驻留的协程
• 未显式 unset() 大变量、未关闭 Co\MySQL 连接导致无法回收的协程
• 在 go() 中启动但逻辑卡死、未 return 的协程
怎么用 stats() 定位协程堆积问题
直接在业务逻辑中插入调试输出即可,例如在 HTTP 请求入口或定时任务里:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
use Swoole\Coroutine;
go(function () {
// 模拟业务处理
Co::sleep(0.1);
$stats = Coroutine::stats();
var_dump([
'now' => $stats['coroutine_num'],
'peak' => $stats['coroutine_peak_num'],
'last_id' => $stats['coroutine_last_id']
]);
});
更实用的做法是结合压测观察趋势:
• 若 coroutine_num 持续 > 80% 的 max_coroutine 值,说明协程调度已吃紧
• 若 coroutine_peak_num 在压测后不回落,大概率存在协程泄漏(比如全局变量持有了协程对象引用)
• coroutine_last_id 突增但 coroutine_num 没同步上升,可能有大量短命协程快速创建销毁,需检查是否滥用 go()
stats() 和 swoole_get_status() 的区别在哪
Coroutine::stats() 只作用于**当前 worker 进程**,且只统计协程层信息;而 swoole_get_status() 返回整个 Server 实例的状态,包含 worker_num、task_worker_num、start_time 等进程级指标,其中也有 coroutine_peak_num 字段,但它是全 server 统计的最大值(非实时)。两者不能混用:
• 查单个 worker 的实时协程水位 → 用 Coroutine::stats()
• 查整个服务是否逼近最大协程上限 → 用 swoole_get_status() 配合 max_coroutine 对比
• 查 fd 是否耗尽(EMFILE 错误根源)→ 必须用 cat /proc/$(pidof php)/limits,stats() 完全不体现这个
stats() 就完事的,真正容易被忽略的是:它不告诉你哪个协程卡住了、占了多少内存、持有哪些资源。要定位具体问题,得配合 swoole_coroutine_stats()(含内存字段)、memory_get_usage() 和 strace 跟踪系统调用。

















