协程id是当前协程在worker进程内的唯一标识符,类型为int,由swoole内部维护,仅在当前进程内有效且可复用;必须通过swoole\coroutine::cid()获取,非协程环境返回0,不可用自增或pid模拟。

协程ID在Swoole中到底指什么
协程ID不是全局唯一递增的整数,而是当前协程在当前进程内的标识符,类型为 int,由 Swoole 内部维护。它只在当前 Worker 进程内有意义,不同进程间可能重复;且协程退出后 ID 可被复用。别把它当成“协程PID”来用。
Swoole\Coroutine::cid() 是唯一可靠方式
必须调用 Swoole\Coroutine::cid() 获取当前协程 ID,不能靠 getmypid()、uniqid() 或自增计数器模拟。该函数在任何协程上下文中都可用(包括 go、defer、parallel 启动的协程),但在非协程环境(如主进程同步代码)返回 0。
常见误用场景:
- 在
onReceive回调里没进协程就直接调Swoole\Coroutine::cid()→ 返回0 - 在
Timer::tick的回调里未显式启用协程 → 仍为0 - 把
cid()结果存到静态变量里跨协程复用 → 值已失效
注意 cid() 在不同 Swoole 版本的行为差异
Swoole v4.8.0+ 对 cid() 做了优化:协程销毁后 ID 不立即回收,而是延迟复用,减少高频创建/销毁时的 ID 波动。但 v4.7.x 及更早版本中,ID 复用更快,容易出现短时间重复。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
如果你依赖 cid() 做日志追踪或上下文绑定,请确保:
- 日志中同时记录
getmypid()和Swoole\Coroutine::cid(),构成唯一标记[pid:12345][cid:678] - 避免用
cid()作为数组键长期缓存数据(协程结束即失效) - 不要在
__destruct或defer中再调用cid()—— 此时协程已处于销毁阶段,行为未定义
调试时怎么确认当前确实是协程上下文
光看有没有调 go() 不够。最稳妥的方式是加一行判断:
if (Swoole\Coroutine::cid() === 0) {
throw new RuntimeException('Not in coroutine context');
}
尤其在封装公共工具函数时,建议开头加此检查。另外,var_dump(Swoole\Coroutine::stats()) 能看到当前进程活跃协程数和最大 ID,辅助验证是否进入预期协程环境。
协程 ID 看似简单,但它的生命周期完全绑定于 Swoole 协程调度器——不是 PHP 用户态能控制的。拿不准的时候,宁可多打一次 Swoole\Coroutine::cid(),也别假设“刚 go 过,肯定有 ID”。










