健康检查接口应返回200 OK表示就绪,503表示未就绪;/healthz仅检查进程存活,/readyz检查DB、Redis等依赖并设超时;DB检查宜用SELECT 1而非db.Ping();健康检查与指标采集应分离端口。

健康检查接口该返回什么状态码
HTTP 健康检查接口必须返回 200 OK 表示服务就绪,其他如 503 Service Unavailable 表示未就绪(例如依赖 DB 连接失败、缓存不可用等)。不能用 204 No Content 或 404,前者会让某些负载均衡器(如 AWS ALB、Nginx)误判为异常,后者直接触发探针失败。
常见错误:返回 200 但 body 是空或非 JSON;应统一返回结构化 JSON,例如:
{"status": "ok", "timestamp": "2024-06-12T10:23:45Z"}
如何实现轻量级 Liveness vs Readiness 分离
Go 应用中通常用两个独立 endpoint:/healthz(liveness)只检查进程是否存活,/readyz(readiness)额外检查关键依赖。不要把两者合并成一个接口——否则扩容时 readiness 失败会阻塞新实例上线,而 liveness 失败又会导致频繁重启。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
-
/healthz仅确认 HTTP server 正常监听,不碰任何外部资源 -
/readyz检查 DB 连接、Redis ping、关键配置加载状态等,每项加超时(如ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)) - 避免在 readiness 中调用耗时外部 API;若必须调用,用
sync.Once缓存最近一次结果,并设 TTL
数据库连接检查容易踩哪些坑
直接执行 db.Ping() 不够可靠:它只验证连接池是否可分配连接,不保证后续查询能成功。更稳妥的做法是执行一条轻量 SQL,例如 PostgreSQL 用 SELECT 1,MySQL 用 SELECT 1 或 SELECT @@version。
注意事项:
- 必须设置上下文超时,防止卡死(
db.QueryRowContext(ctx, "SELECT 1")) - 不要复用主业务的
*sql.DB连接池做健康检查——高并发下可能被占满,导致健康检查假失败 - 如果使用 GORM,别调
db.First(&dummy),改用db.Raw("SELECT 1").Scan(nil)避免 ORM 开销
如何让健康检查不干扰 Prometheus 指标采集
很多团队把健康检查和指标暴露混在同一个端口(如 :8080/metrics),这会导致问题:Kubernetes 的 readiness probe 频繁请求 /metrics,拉高指标采集负载,甚至触发限流。
正确做法:
- 健康检查走独立端口(如
:8081/healthz),指标走:9090/metrics - 若必须共用端口,确保健康检查路径不触发
promhttp.Handler()的 metrics 收集逻辑(即路径不能是/metrics的前缀) - 禁用健康检查路径的指标记录:在
promhttp.HandlerOpts{DisableCompression: true, Registry: nil}中显式排除










