Go任务队列监控需盯住消费者吞吐、处理耗时恶化、资源耗尽三类指标;goroutine泄漏首看go_goroutines持续增长,须用GaugeVec加固定label区分来源,并按队列类型差异化设阈值;task_queue_length与task_processing_seconds的P95须分开告警;for时长须为evaluation_interval整数倍,且Alertmanager路由必须包含queue_name和instance标签。

Go 任务队列的监控不能只看“有没有堆积”,得盯住三类指标:消费者吞吐是否跟得上、任务处理是否在恶化、资源是否被耗尽。否则等告警响起来,队列已经雪崩了。
go_goroutines 持续增长是 goroutine 泄露的第一信号
任务队列常依赖 channel + goroutine 实现消费,但忘记 close channel 或漏写 defer wg.Done() 会导致 goroutine 累积。Prometheus 默认暴露 go_goroutines,但它本身不带业务上下文——你得靠 label 区分是 worker 池还是定时器泄漏。
- 在注册自定义 goroutine gauge 时,必须用
GaugeVec并固定 label 名称,比如[]string{"queue_name", "role"},避免运行时动态加 label 导致指标注册失败 - 告警阈值别硬写
go_goroutines > 1000;应按队列类型差异化设置:核心下单队列设 300,日志归档队列可放宽到 800 - 配合
rate(go_goroutines[5m]) > 2判断“每分钟新增 goroutine 是否异常”,比绝对值更能早发现泄漏趋势
task_queue_length 和 task_processing_seconds 的 P95 必须分开告警
队列长度(如 Redis list length、Kafka lag)和单任务处理耗时是两个维度:前者反映积压压力,后者反映执行健康度。混在一起告警会掩盖真实问题——比如长度突增但耗时正常,大概率是上游突发流量;长度稳定但 P95 耗时翻倍,说明下游依赖(DB/HTTP)出问题了。
- 用
histogram_quantile(0.95, sum(rate(task_processing_seconds_bucket[5m])) by (le, queue_name))计算分位数,别用 avg —— 单个卡死任务会拉高均值,误判为整体变慢 -
task_queue_length告警建议用绝对值 + 持续时间组合:task_queue_length > 1000 for: 1m(防瞬时毛刺),task_queue_length > 5000 for: 5m(真积压) - 若用自定义指标(如从 Redis
LLEN抓取),注意采集间隔要小于 Prometheus 的evaluation_interval,否则for逻辑失效
alert rule 的 for 时长必须小于 evaluation_interval
Prometheus 不会每秒评估规则,而是按配置的 evaluation_interval(默认 1m)周期性跑一遍。如果 for: 30s,它永远无法满足——因为两次评估至少隔 60 秒,根本凑不够 30 秒连续触发条件。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 检查你的
prometheus.yml中global.evaluation_interval值,告警规则的for至少要是它的整数倍,推荐设为2m或5m - 对关键队列(如下单、支付回调),可配两条规则:一条
for: 1m快速响应毛刺,一条for: 5m过滤噪音,用不同severity标签分流 - 别在
expr里用[1m]这种极短窗口——rate(...[1m])在低频队列上极易因采样点缺失返回NaN,导致规则静默失效;[5m]是更稳妥起点
Alertmanager 路由必须匹配 queue_name 和 instance
没有 queue_name 标签的告警,在 Alertmanager 里无法按队列做分组或静音;没有 instance 就没法定位到具体服务实例——所有告警都堆在一个通知里,等于没告警。
- 在 Go 代码中注册指标时,确保
task_processing_seconds这类 histogram 的WithLabelValues("payment_queue")显式传入业务队列名 - Alertmanager 的
route配置里,group_by: [queue_name, instance, severity]是底线,缺一不可 - 测试时用
curl http://alertmanager/api/v2/alerts | jq '.[] | select(.labels.queue_name == "payment_queue")'验证标签是否透出成功
最常被忽略的是:告警规则热加载后,旧规则不会自动失效。如果你改了 for 时长但没重启 Prometheus,新规则压根不生效——得确认 promtool check rules 通过,且 Prometheus 日志里出现 Loaded configuration file 才算真正加载成功。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










