Go Web服务健康监控需区分/health(存活)与/ready(就绪),外部依赖须设超时并返回503/500及具体错误,指标用prometheus/client_golang暴露,优雅退出用http.Server.Shutdown()配合SIGTERM。

Go Web服务的运行状态监控,不是加个 /health 接口就完事了——它得真实反映服务是否能干活,而不是“进程还活着”。核心在于:用标准方式暴露可观测数据,让 Prometheus 能拉、Kubernetes 能探、人能快速定位问题。
健康检查接口不能只返回 {"status": "ok"}
这是最常见也最危险的误区。Kubernetes 的 livenessProbe 默认 1 秒超时,如果 handler 里偷偷连数据库或查磁盘,超时就会反复杀进程。真正的健康检查必须:
- 区分
/health(存活)和/ready(就绪):前者看自身 goroutine、内存是否异常;后者才查 DB/Redis 等依赖 - 所有外部调用必须带
context.WithTimeout,比如db.PingContext(ctx, 2*time.Second) - 失败时返回 HTTP 503(就绪态)或 500(存活态),并在 JSON body 中标注具体失败项,如
{"status": "error", "details": {"redis": "timeout"}} - 避免在 handler 里做耗时计算(如读取大文件、解析复杂配置),这些应提前初始化或异步更新
指标暴露必须用 prometheus/client_golang,别手写 /metrics
自己拼接文本格式的 metrics 不仅易错,还会被 Prometheus 拒绝(格式校验失败)。官方 SDK 能自动注册 Go 运行时指标(GC、goroutines、heap),还能安全处理并发写入:
- 用
promhttp.Handler()暴露/metrics,不要自己实现http.HandlerFunc - 业务指标优先用
CounterVec或HistogramVec,label 维度要克制(例如用method和status,但别用user_id) - HTTP 埋点务必走中间件,而不是每个 handler 手动调
counter.Inc();Gin/Echo 可用promhttp.InstrumentHandlerDuration,标准库建议封装http.Handler包装器 - 健康接口(如
/healthz)禁止埋点——它每 10 秒被 kubelet 调一次,会严重污染请求量指标
http.Server.Shutdown() 是优雅退出的唯一可靠方式
直接 kill 进程会导致连接中断、指标上报不全、Prometheus 抓取失败。尤其在 Kubernetes rolling update 场景下,必须配合信号处理:
立即学习“go语言免费学习笔记(深入)”;
- 监听
SIGTERM(k8s 发送的终止信号),触发server.Shutdown() -
Shutdown()会等待活跃请求完成,但需设置合理context.WithTimeout(如 10 秒),避免卡死 - 关闭前可主动调用
prometheus.Unregister()清理临时指标(非必需,但利于调试) - 别用
http.ListenAndServe()启动——它没有 Shutdown 控制权,必须显式构造http.Server实例
最难的不是写代码,而是定义什么算“健康”:数据库连得上但慢了 5 秒算不算?磁盘剩 5% 算不算?这些阈值必须和运维、SRE 对齐,并写进 Prometheus 告警规则,而不是藏在 Go 代码里硬编码判断。










