Go服务健康检查必须区分/livez(仅进程存活)和/healthz(含依赖就绪),前者禁调外部依赖、超时1秒,后者检查DB等依赖、超时10秒,二者混用会导致Kubernetes误杀Pod或流量误入故障实例。

Go 语言本身没有“自愈能力”,所谓健康检查接口的自愈,实际是通过可编程的故障探测 + 状态重置 + 服务重启逻辑来模拟。关键不在于接口是否返回 200,而在于它能否触发下游真实恢复动作。
健康检查接口不该只返回 status=ok
很多初学者把 GET /health 写成固定返回 {"status": "ok"},这根本不是健康检查,只是“心跳”。真正的健康检查必须验证核心依赖:数据库连接、Redis 可写、关键 goroutine 是否卡死、本地磁盘剩余空间是否低于阈值。
- 用
db.PingContext(ctx)替代简单 ping,避免阻塞主线程 - 对 Redis 执行
SET health:check "1" EX 1而非PING,验证写能力 - 用
runtime.NumGoroutine()设上限(如 > 10000 则告警),但不要直接 kill - 检查
/proc/mounts或调用syscall.Statfs获取磁盘可用率,低于 5% 触发清理逻辑
如何让健康检查触发自动恢复动作
HTTP 接口本身不能“自愈”,必须把检查结果映射到可执行操作。典型做法是:健康检查失败时,主动调用内部 reset 函数,而不是等外部重启进程。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 在
healthzhandler 中,若检测到 DB 连接超时,调用reconnectDB()并记录reconnect_attempt_count指标 - 避免在 handler 里做耗时操作(如重启整个服务),改用
sync.Once+ 后台 goroutine 异步执行恢复 - 使用
atomic.CompareAndSwapInt32控制恢复动作最多执行一次/分钟,防抖 - 恢复成功后,通过
http.Redirect或设置X-Retry-After: 30告知上游暂缓重试
为什么 livenessProbe 和 readinessProbe 要分开设计
Kubernetes 的 livenessProbe 失败会 kill container,readinessProbe 失败则摘流量——两者语义完全不同,混用会导致服务雪崩。
立即学习“go语言免费学习笔记(深入)”;
-
/health/live应只检查进程是否存活(如atomic.LoadInt32(&isRunning) == 1),绝不查 DB;否则 DB 挂了会反复 kill pod -
/health/ready才查 DB、Redis、依赖服务,失败时仅下线该实例,给恢复留出时间窗口 - 两个 endpoint 必须用不同 timeout:live 接口
timeoutSeconds: 1,ready 接口timeoutSeconds: 10 - Go 里用不同 mux 路由注册,避免中间件干扰(比如 auth middleware 不该加在 live 接口上)
最易被忽略的是状态持久化:恢复动作执行后,得把“已尝试修复”写入内存变量或本地文件,否则下次健康检查又重复触发。别指望每次请求都从零开始判断——那不是自愈,是自扰。

















