Hyperf 3.0 的 Context 在协程退出时自动清理数据,保障协程间隔离;底层绑定协程 ID 独立内存,Swoole 自动回收,异常中断或子协程不继承(除非显式 copy)也适用。

Hyperf 3.0 的 Context 确实会在协程退出时自动清理所存数据,这是它保障协程间数据隔离的核心机制之一。
协程退出时上下文自动释放
Context 底层调用 Coroutine::getContextFor($coroutineId),将键值对绑定到当前协程 ID 对应的独立内存空间。当该协程执行完毕、被调度器销毁时,Swoole 会自动回收其上下文容器,无需手动调用 Context::delete() 或额外清理逻辑。
这意味着:
- 协程结束 = 上下文数据彻底消失,不会残留或污染其他协程
- 即使协程因异常中断(如未捕获的 Exception),只要协程生命周期终止,上下文仍会被释放
- 子协程默认不继承父协程 Context,除非显式调用
Context::copy()
哪些情况不会自动清理?
自动清理只在协程真正退出时生效。以下情形需特别注意:
- 协程长期运行(如常驻的
go任务)且未主动退出,Context 数据将持续存在 - 使用
Co::defer()注册的回调中又创建了新协程,原 Context 不会传递过去,但 defer 回调本身仍处于原协程上下文中 - 在非协程环境(如命令行脚本、单元测试)中,Context 退化为静态数组,此时不触发自动清理,需自行管理
推荐的使用姿势
为确保清晰可控,建议遵循这些实践:
- 只在请求生命周期内使用
Context::set()存储临时状态(如用户 ID、请求 ID、DB 连接实例) - 避免在全局初始化、
@OnWorkerStart或常驻进程里往 Context 写数据——这些地方没有“所属协程”概念 - 若需跨协程传递少量必要信息(如 trace_id),优先用
Context::copy()显式复制,而非依赖隐式继承 - 调试时可用
Context::all()查看当前协程全部上下文内容,但生产环境慎用
和 RequestInterface::getAttribute() 的区别
RequestInterface::getAttribute() 是 PSR-7 请求对象的属性存储,仅限该 Request 实例生命周期,不穿透到 DB 查询、Redis 调用等异步操作中;而 Context 是协程级全局可见的,所有在该协程中发起的协程客户端(如 Hyperf\DbConnection\Db、Hyperf\Redis\Redis)都能访问到。两者定位不同,不可替代。


















