log_id在协程间丢失是因为PHP传统上下文(如$_SERVER、全局变量、静态属性)不随协程切换自动隔离或继承;必须用Co::setContext()在onRequest入口初始化,并由子协程自动继承,配合SWOOLE_HOOK_ALL确保同步调用路径也能获取上下文。

为什么 log_id 在协程间会丢失?
因为 Swoole 协程是轻量级用户态线程,$_SERVER、全局变量、静态属性这些 PHP 传统上下文载体,在协程切换时不会自动隔离或继承。你在一个协程里设置的 $log_id,另一个协程里根本看不到——它不是协程安全的。
常见错误现象:日志里出现多个请求共用同一个 log_id,或者 log_id 突然为空、变成 0、甚至复用上一个已结束协程的 ID。
- 别用
static $log_id或global $log_id存 ID - 别依赖
$_REQUEST/$_SERVER['request_id']—— 这些在协程内不随上下文传递 - 别在中间件外手动调
Co::getcid()拼 ID —— 协程 ID 会复用,且无法跨进程/worker 唯一
用 Context + Hook 实现自动透传
Swoole 4.4+ 内置了 Co::getContext() 和 Co::setContext(),配合 Coroutine::create() 的上下文继承机制,可以安全携带 log_id。关键是要在请求入口(如 HTTP Server 的 onRequest)就初始化,并让所有子协程自动继承。
实操建议:
- 在
onRequest回调开头生成唯一log_id(推荐用bin2hex(random_bytes(8)),比microtime(true)更抗并发冲突) - 立即调用
Co::setContext(['log_id' => $log_id]) - 后续所有通过
go、defer、Parallel启动的协程,都会自动继承该 context - 日志写入前统一从
Co::getContext()['log_id'] ?? 'unknown'取值
示例片段:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
// onRequest 中
$log_id = bin2hex(random_bytes(8));
Co::setContext(['log_id' => $log_id]);
// 日志封装函数中
function log_info($msg) {
$ctx = Co::getContext();
$log_id = $ctx['log_id'] ?? 'unknown';
echo "[{$log_id}] {$msg}\n";
}
如何兼容非协程调用路径(比如同步 DB 查询、外部 SDK)?
有些老 SDK 或扩展(如某些 Redis 客户端、curl 封装)可能绕过协程调度,直接走同步阻塞调用,这时 Co::getContext() 会失效——因为执行不在协程栈里。
解决思路不是硬改 SDK,而是用 Swoole 的 hook_flags 主动接管底层系统调用:
- 启动时开启完整 hook:
Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL); - 特别注意:如果用了
mysqlnd,需额外加SWOOLE_HOOK_NATIVE_CURL才能 hook 住 PDO::query 中的底层 socket - 验证是否生效:在同步调用前后打日志,确认
Co::getContext()始终可读
若仍有部分代码无法 hook(如某些 C 扩展),临时方案是把 log_id 作为参数显式透传,而非依赖上下文。
生产环境要注意的三个细节
协程日志追踪不是设个 context 就完事。容易被忽略但实际影响排查效率的点:
-
log_id必须带前缀(如req_),否则和 trace_id、span_id 混淆,ELK 里分不清来源 - Worker 进程重启后,
Co::getContext()是空的——必须确保每个新请求都重置,不能靠“首次初始化”逻辑 - 使用
Parallel或Channel::pop(timeout)时,超时协程会被销毁,但 context 不会自动清理,大量短生命周期协程可能轻微内存泄漏(Swoole 5.0.1+ 已修复,旧版本建议避免在循环里高频创建)
最稳妥的做法:每次请求入口做 clean + init,不要假设 context 存在;日志格式固定字段顺序,方便 grep 和结构化解析。

















