健康检查必须分离 /healthz 和 /readyz:前者仅检查进程存活(≤100ms,不查外部依赖),后者检查业务就绪(≤2s,带 context 超时并发探活),响应统一 200 但含 status 字段,keepalived 脚本需用 curl -f 并重试。

Go 微服务的健康检查接口不能只返回 200 OK,否则 Kubernetes、Keepalived 或 Consul 会误判“服务可用”,而实际依赖已断、goroutine 卡死或数据库连接池耗尽。必须分层暴露、带超时、可组合、可观察。
/healthz 和 /readyz 必须拆开,不能合并在一个端点
很多团队图省事只写一个 /health,结果导致 Kubernetes 频繁重启 Pod 或 LB 误发流量。liveness 和 readiness 的语义完全不同:
-
/healthz(或/live)只检查进程级存活:HTTP server 是否 accept 连接、关键 goroutine 是否 panic、内存是否接近 OOM —— 不查任何外部依赖,响应时间 ≤ 100ms -
/readyz(或/ready)检查业务就绪:DB 连接池是否 ready、Redis 是否可写、下游 gRPC 服务是否响应 —— 同步调用,超时必须设为context.WithTimeout,建议 ≤ 2s - 如果共用一个端点,K8s 的
livenessProbe可能因 DB 慢而杀掉本该存活的 Pod;readinessProbe又可能因 liveness 的轻量逻辑漏掉真实依赖故障
依赖检查必须带 context 超时,且不能阻塞主 handler
常见错误是直接调用 db.Ping() 或 redisClient.Ping(),没传 context,一旦 DB 网络卡住,整个健康检查 hang 住,K8s 探针超时后反复 kill —— 这不是高可用,是自毁。
- 每个依赖检查都应封装成
func() (string, error),内部用context.WithTimeout(ctx, 2*time.Second) - 避免在 handler 里串行执行所有检查:DB → Redis → Kafka,而应并发启动并等待全部完成,或用
errgroup.Group统一控制超时 - 返回 JSON 时,即使某个依赖失败,也别直接
http.Error(w, ... , 503)—— 应统一返回200,但把"status": "degraded"或"status": "down"写进响应体,让监控系统自己判断
Keepalived 或 Nginx upstream 依赖脚本检测时,只认退出码,不解析响应体
Keepalived 的 track_script 只看脚本返回值:0 表示健康,非 0 触发 VIP 漂移。它不会读你的 JSON,也不会等你返回 503。
- 写检测脚本时,必须用
curl -f -s -o /dev/null http://localhost:8080/readyz,加-f才能让 HTTP 非 2xx 时返回非零退出码 - 别用
curl -I判断状态码再 if 判断 —— 多余且易出错;更别用wget,它默认不校验状态码 - Keepalived 默认每 2 秒执行一次脚本,若 Go 服务启动慢,脚本可能在
/readyz还没 ready 就失败 —— 建议在脚本里加重试(最多 3 次,间隔 1s),或 Keepalived 配置rise 3 fall 2
响应结构要兼容主流平台,字段名别自创
Kubernetes、Consul、Nacos、Spring Cloud Gateway 对 JSON 字段有隐式约定,乱命名会导致探针识别失败。
- 必含字段:
"status"(值为"UP"、"DOWN"或"DEGRADED",大小写敏感)、"timestamp"(RFC3339 格式) - 推荐字段:
"checks"(map[string]any,记录各依赖详情)、"version"、"service" - 别用
"healthy": true或"is_ok": 1—— Consul 会忽略,K8s readiness 默认只看状态码,但 Prometheus exporter 或 Grafana 告警规则常依赖status字段值 - 始终设置
w.Header().Set("Content-Type", "application/json"),某些 Ingress 控制器(如 nginx-ingress)会因类型缺失拒绝转发
最易被忽略的其实是超时控制粒度 —— 不是整个 handler 设 timeout,而是每个依赖检查单独设;还有就是 Keepalived 脚本里忘了 -f 参数,导致 HTTP 503 被当成健康。这两个点踩中一个,VIP 就会漂得毫无规律。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











