Golang如何进行微服务的监控与告警

Prometheus+Grafana是Go微服务监控主流方案,需用官方SDK暴露规范指标端点,通过中间件自动埋点、路由归一化、禁用健康接口埋点,告警逻辑应写在Prometheus而非Go代码中。

用 Prometheus + Grafana 搭监控,别自己造轮子

Go 微服务监控的主流方案是 Prometheus 拉取指标 + Grafana 可视化 + Alertmanager 告警,不是用 Go 写个 HTTP 接口吐 JSON 就算监控了。自己维护指标采集、存储、聚合、告警路由,成本远高于集成标准栈。

关键点在于:Go 服务要暴露符合 Prometheus 规范的指标端点,其他交给基础设施。

  • github.com/prometheus/client_golang 是官方 SDK,必须用它,不要手写 /metrics 响应
  • 默认指标(如 goroutines 数、GC 次数、HTTP 请求延迟)开箱即用,调 promhttp.Handler() 即可暴露
  • 自定义业务指标(比如订单处理失败数)要用 prometheus.NewCounterVec()NewHistogramVec(),注意 label 维度别设计太宽(如用用户 ID 当 label 会爆炸)
package main

import (
	"net/http"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	orderCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "order_processed_total",
			Help: "Total number of orders processed",
		},
		[]string{"status"}, // 

只用 status,不用 user_id ) ) func init() { prometheus.MustRegister(orderCount) } func main() { http.Handle("/metrics", promhttp.Handler()) http.HandleFunc("/process", func(w http.ResponseWriter, r *http.Request) { orderCount.WithLabelValues("success").Inc() w.WriteHeader(http.StatusOK) }) http.ListenAndServe(":8080", nil) }

HTTP 中间件自动埋点,避免每个 handler 手动统计

手动在每个 handler 里调 httpDuration.WithLabelValues(...).Observe(...) 容易漏、难维护。应该用中间件统一采集请求路径、方法、状态码、延迟。

注意:promhttp.InstrumentHandlerDuration 等内置中间件只适合简单场景;高并发下需避免在每次请求中新建 prometheus.Labels map,应复用或预分配。

  • promhttp.InstrumentHandlerDuration + promhttp.InstrumentHandlerCounter 覆盖 80% 场景
  • 路径带参数(如 /user/:id)时,务必先做路由归一化(例如把 /user/123/user/{id}),否则指标维度爆炸
  • 不要对健康检查接口(/healthz)埋点——它高频调用会污染真实业务指标

告警规则写在 Prometheus,不在 Go 里触发 HTTP 请求

常见错误:在 Go 代码里监听某个条件(如错误率 > 5%),然后 http.Post("http://alert-svc/notify")。这绕过了 Prometheus 的去重、静默、分组、抑制等核心能力,极易重复告警、漏告警。

正确做法是把告警逻辑全写进 alert.rules.yml,由 Prometheus 定期评估并推给 Alertmanager

  • 告警表达式用 rate(http_request_duration_seconds_count{job="my-service"}[5m]) 这类 PromQL,不是 Go 里的 if 判断
  • 告警 label(如 severity: "critical")和 annotations(如 summary: "High error rate on {{ $labels.instance }}")都在 YAML 里定义
  • Go 服务只需确保指标可被 Prometheus 正确抓取(检查 scrape_configs 和目标状态页 /targets

本地开发时用 docker-compose 快速验证整套链路

不启动完整 K8s 集群也能验证监控是否生效:用 docker-composeprometheusgrafanaalertmanager 和你的 Go 服务,5 分钟内就能看到指标和告警。

容易卡住的点:

  • Prometheus 抓不到 Go 服务?检查容器网络:Go 服务暴露的 :8080/metrics 是否能被 Prometheus 容器 curl 通(docker exec -it prometheus curl http://go-service:8080/metrics
  • Grafana 查不到数据?确认数据源已添加且指向 http://prometheus:9090(不是 localhost
  • Alertmanager 没收到告警?看 Prometheus UI 的 Status > Alerts 页面是否显示 FIRING,再查 Alertmanager 的 /alerts 接口

最常被忽略的是指标生命周期管理:上线新服务要加 job,下线旧服务要及时删 job,否则 Prometheus 会持续报 target down 错误,干扰真实问题定位。