/health 不等于健康度上报,因其仅为同步、无状态的二值探针端点,缺乏时间序列、维度标签和历史趋势;真正的健康度上报需主动暴露带标签的指标(如 gauge/counter)至 /metrics,供 Prometheus 拉取分析。

直接暴露 /health 接口不能算“健康度上报”,它只是被动响应探测;真要上报,得主动把状态推给监控系统(如 Prometheus)或注册中心(如 Consul),或者让服务自身具备可被拉取的指标端点。
为什么 /health 不等于健康度上报
标准 /health 是一个同步、无状态、只读的 HTTP 端点,常用于 Kubernetes 的 liveness/readiness probe。它不携带时间序列、不记录历史、不区分维度(比如按数据库实例、缓存节点拆分),更不会自动上报——它等着别人来问。
健康“度”强调可观测性:要能反映变化趋势、失败率、依赖延迟、资源水位等连续值,而不仅是“ok / failing”二值判断。
-
/health返回{"status":"ok"}→ 适合做存活探针,不适合做 SLO 计算 - 上报健康度 → 需要指标类型(如
gauge表示当前连接数,counter表示累计错误数)+ 标签(db="postgres-01",cache="redis-shard-2")+ 拉取路径(/metrics) - 若强行用
/health返回带 timestamp 和 metrics 的 JSON,监控系统无法解析,Prometheus 会直接报错text format parsing error
用 prometheus/client_golang 暴露可拉取指标
Gin 本身不提供指标采集,必须引入 Prometheus 客户端,并注册指标到全局 registry,再挂载 /metrics 路由供拉取。
- 不要手动拼接
text/plain响应体——用promhttp.Handler(),它自动处理格式、编码、gzip、header - 避免在 handler 里调用
prometheus.MustRegister(),注册应在main()初始化阶段完成,否则并发注册 panic - 关键指标建议:一个
gauge表示 DB 连接池空闲数(db_connections_idle{instance="user-svc"}),一个counter统计健康检查失败次数(health_check_failures_total{dependency="redis"})
示例片段:
import (
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
dbConnGauge = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "db_connections_idle",
Help: "Number of idle connections in the pool",
ConstLabels: prometheus.Labels{"service": "user-api"},
})
)
func init() {
prometheus.MustRegister(dbConnGauge)
}
func main() {
r := gin.Default()
r.GET("/metrics", gin.WrapH(promhttp.Handler()))
// ... 启动后定期更新 dbConnGauge.Set(float64(pool.Stats().Idle))
}
依赖状态怎么带标签上报
健康检查不是“全好 or 全挂”,而是每个依赖独立打分。上报时必须打标,否则指标无法下钻分析。
- 错误类型要分离:
health_dependency_status{dependency="mysql",status="up"}是 gauge;health_dependency_latency_seconds{dependency="redis",quantile="0.95"}是 histogram - 避免把多个依赖状态塞进一个指标里(如
health_all_deps),这会让 PromQL 查询失效、告警难配置 - 如果依赖不可达,不要让整个
/metrics500——应设为NaN或保持上一值(用gauge.Set(math.NaN())或不更新),保证指标端点始终可用 - Kubernetes 中,
readinessProbe可继续用/health,而metrics单独走 service monitor 或 pod monitor 抓取
别忽略指标生命周期和内存泄漏
高频更新指标(比如每秒更新一次连接数)时,prometheus.NewGauge 创建的对象本身不泄漏,但若反复 MustRegister 同名指标,会导致 panic;若用 prometheus.NewPedanticRegistry() 可捕获重复注册问题。
- 不要在中间件里 new 指标对象——指标应单例,全局复用
- HTTP handler 中调用
gauge.Set()是线程安全的,但注意 float64 转换精度(如纳秒转秒记得除以1e9) - 若服务启停频繁,用
prometheus.Unregister()清理旧指标(仅限测试/热重载场景,生产一般不 unregister) - 真实微服务中,建议把健康度指标和业务指标分开命名空间(如
health_db_*vsapi_request_*),避免命名冲突和查询混淆
最易被跳过的点:指标没有单位标注、没有 HELP 文本、标签值含非法字符(如空格、斜杠),会导致 Prometheus 拒绝 ingestion —— 这类错误不会立刻报错,而是静默丢弃数据。


















