直接用go启动goroutine不够用,因其缺乏统一调度、错误隔离、限流和重试机制,易导致服务打爆、panic崩溃、goroutine泄漏、无背压及不可观测等问题。
为什么直接用 go 启动 goroutine 不够用
因为缺乏统一调度、错误隔离、限流和重试机制。比如批量调用第三方 API 时,100 个 go request() 可能瞬间打爆目标服务,或某个 panic 导致整个程序崩溃;也没有办法控制并发数、记录失败任务、或在失败后自动重试。
真正需要的是一个带缓冲、可控制、有状态反馈的队列层,而不是裸奔 goroutine。
- goroutine 泄漏:任务函数里忘了 recover 或阻塞未处理,goroutine 永远卡住
- 无背压:生产者 push 太快,内存暴涨(尤其用无缓冲 channel)
- 不可观测:不知道当前积压多少任务、成功/失败率、耗时分布
用 sync.WaitGroup + channel 实现基础可控队列
这是最轻量、不依赖外部库的实现方式,适合中小规模(千级以内任务)、对可靠性要求不极端的场景。
核心结构是带缓冲的 chan 做任务入口,固定数量 worker 从 channel 消费,WaitGroup 控制生命周期: