/health不能只返回200 OK,因其需区分进程存活与业务就绪:/health/live仅做轻量快照(如goroutine数、内存),而/health/ready必须同步探测DB/Redis/gRPC等依赖,任一失败即返回503并带具体错误项,避免流量涌入导致故障。

为什么/health不能只返回200 OK
很多服务上线后在 Kubernetes 里频繁重启,根源就是把 /health 当成 /ping 用——只检查进程是否存活,不验证 DB、Redis 或下游 gRPC 是否真能连上。Kubelet 看到 HTTP 200 就认为“就绪”,结果流量打进来立刻报错。
-
/health/live(或/healthz)只做轻量快照:检查runtime.NumGoroutine()是否异常飙升、关键 channel 是否已 close、内存是否接近 cgroup limit -
/health/ready(或/readyz)必须同步探测依赖:DB 调db.PingContext(ctx, 2*time.Second),Redis 用client.Ping(ctx).Err(),gRPC 连接查conn.GetState() == connectivity.Ready - 任一依赖超时或失败,
/health/ready必须返回503 Service Unavailable,且响应体带具体失败项(如{"redis": "timeout"}),不能只写{"status": "down"}
如何避免健康检查拖垮主服务
探针请求卡住,会阻塞整个 HTTP server 的 goroutine 池,尤其在高并发场景下,一个慢检查可能让所有请求排队等待。
- 用独立的
http.ServeMux注册健康端点,和业务路由完全隔离,防止业务 panic 或中间件影响探针 - 所有依赖检查必须带 context 超时:
context.WithTimeout(context.Background(), 1500*time.Millisecond),总耗时控制在 2s 内 - 非强依赖项(如监控上报、日志服务)改用异步检查 + 缓存结果,不要阻塞
/health/ready响应流 - 别在 handler 里 new redis.Client 或 sql.DB 实例——复用服务启动时已初始化的全局 client,否则每次探针都建连接,fd 很快耗尽
怎么让 Kubernetes 正确使用 liveness 和 readiness
K8s 探针配置不对,等于白写健康接口。常见错误是把两个 probe 都指向同一个路径,或者 timeout 设得太短。
-
livenessProbe用/health/live,initialDelaySeconds: 10,timeoutSeconds: 1,失败后重启容器 -
readinessProbe用/health/ready,initialDelaySeconds: 15(给 DB 连接池 warmup 留时间),timeoutSeconds: 3,失败时从 Service Endpoint 列表剔除 - 务必设置
periodSeconds: 5和failureThreshold: 3,避免网络抖动误判;successThreshold保持默认 1 即可 - 响应头必须加
Content-Type: application/json; charset=utf-8,否则某些 Ingress(如 nginx)会截断 JSON 导致探针解析失败
哪些细节容易被忽略但会导致线上故障
健康检查逻辑本身简单,但部署环境、依赖行为、Go 运行时特性带来的坑,往往在压测或发布后才暴露。
立即学习“go语言免费学习笔记(深入)”;
- etcd 注册的心跳 TTL(如
LeaseGrant(5))必须大于心跳间隔,且用流式续租(lease.KeepAlive),轮询LeaseRenew在网络延迟高时极易漏发 - 第三方库如
go-health默认启用 CPU/Mem 检查,在容器里常因 cgroup 路径权限问题返回 500,应禁用默认 checker:health.New(health.WithCheckers()) - gRPC 客户端没配
grpc.WithKeepaliveParams(keepalive.KeepaliveParams{Time: 30*time.Second}),连接假死后不会自动重连,/health/ready检查conn.GetState()会一直返回Connecting - 服务退出前没调
lease.Revoke(),etcd 里残留 key 会阻塞新实例注册,表现为滚动更新卡在 “waiting for pod to become ready”


















