Kratos自v2.4起已移除kratos/pkg/sync/pool包,因其与sync.Pool定位重叠且维护成本高;应改用标准库sync.Pool复用对象,或基于chan+for range实现可控worker pool。

Kratos 里没有内置协程池,别直接 import “kratos/pkg/sync/pool”
Kratos 官方从 v2.4 开始已移除 kratos/pkg/sync/pool 包,文档和旧示例里残留的用法会 panic 或编译失败。它早期确实提供过 Pool 类型,但因与 Go 原生 sync.Pool 定位重叠、维护成本高、且实际业务中多数场景更适合显式控制 goroutine 生命周期,最终被弃用。
常见错误现象:
- 导入
"kratos/pkg/sync/pool"报错cannot find package - 调用
pool.New()或pool.Go()时 panic:"undefined: pool" - 误以为 Kratos 自带“任务队列+动态扩缩容”协程池,结果发现只是个简单 wrapper
正确做法是:用标准库 sync.Pool 管理**对象复用**(如 buffer、proto message),用 worker pool 模式自己封装 goroutine 控制逻辑——比如基于 chan + for range 的固定 worker 数量调度器。
高频 goroutine 泄漏的三个典型现场
不是开得多就并发高,没控住就变资源黑洞。
-
http.TimeoutHandler超时后,底层 goroutine 并未自动回收,若 handler 内部还启了子 goroutine(比如日志异步上报、metric 打点),这些 goroutine 会持续运行直到函数自然结束——而它可能永远不结束 - 忘记
close(ch)导致for range ch卡死,整个 worker goroutine 永久阻塞 - 在 defer 中启动 goroutine(例如
defer func() { go cleanup() }()),但外围函数已 return,cleanup 可能访问已释放的栈变量或关闭的 channel,行为不可预测
验证是否泄漏:跑一段时间后执行 curl http://localhost:8000/debug/pprof/goroutine?debug=1,看数量是否持续上涨;或者用 runtime.NumGoroutine() 打点监控。
替代方案:用 buffered channel + 固定 worker 数控并发
比“通用协程池”更可控、更贴近 Kratos 的设计哲学——它鼓励你把并发逻辑收口、可测、可观察。
一个轻量实现示意:
type WorkerPool struct {
tasks chan func()
}
<p>func NewWorkerPool(size int) *WorkerPool {
return &WorkerPool{
tasks: make(chan func(), 1024), // 缓冲区防阻塞调用方
}
}</p><p>func (wp *WorkerPool) Start() {
for i := 0; i </p><p>func (wp *WorkerPool) Submit(task func()) {
wp.tasks </p>
- 缓冲通道容量要设合理值,太小会导致 Submit 阻塞;太大则内存浪费,且背压信号弱
- Start 必须在 Submit 前调用,否则任务写入无消费者,channel 会永久阻塞
- 如果需要等待所有任务完成,得额外加
sync.WaitGroup,不能依赖 channel 关闭
Kratos 中真正该关注的并发控制点
框架本身在几个关键路径做了并发约束,你改配置比写池子更有效:
-
transport/http.Server的ReadTimeout/WriteTimeout:防慢连接耗尽 goroutine -
client/http.Client的Transport.MaxIdleConnsPerHost:限制下游连接数,间接控上游 goroutine 创建节奏 - 中间件里用
context.WithTimeout包裹下游调用,避免单个超时请求拖垮整条链路
真正难的不是“怎么开 goroutine”,而是“什么时候该让它停、停不下来怎么办”。Kratos 不提供银弹,但留好了 hook 和可观测入口——比如 middleware/recovery 里捕获 panic 后打日志,middleware/tracing 里标记 span 生命周期,这些才是高并发稳态的关键。











