runtime.NumGoroutine() 是监控协程数最直接方式,需配合阈值检查、信号量限流、pprof定位及worker pool等结构化手段防控协程爆炸。
使用 runtime.NumGoroutine() 是监控 Go 程序中当前活跃协程数量最直接的方式,但它本身不防止协程爆炸——真正起作用的是配合它做主动检查、限流和资源控制。
调用 runtime.NumGoroutine() 返回当前正在运行或处于等待状态(如阻塞在 channel、锁、syscall)的 goroutine 总数。它开销极小,可高频调用:
不能只“看”不“拦”。应在创建 goroutine 的入口处加阈值判断,避免无节制 spawn:
go f() 前检查:if runtime.NumGoroutine() > 5000 { log.Warn("too many goroutines, skip task") }
semaphore.NewWeighted(100))统一管理并发度,比单纯数数字更可靠单纯告警不够,需快速定位谁在疯狂启协程:
pprof:在服务中注册 net/http/pprof,访问 /debug/pprof/goroutine?debug
=2 查看完整堆栈
select、chan receive 或 time.Sleep 的 goroutine,它们可能已“挂起”却未退出go tool pprof 分析火焰图,识别高频创建 goroutine 的函数路径预防比监控更重要。从编码习惯上减少失控风险:
go doWork(i),改用 worker pool 模式(固定 N 个消费者处理任务队列)ctx.Done()
errgroup.Group 替代手动管理一组 goroutine,天然支持 cancel 和错误传播