go应用健康探针需区分/livez(检查进程是否卡死,不依赖外部服务)和/readyz(检查依赖就绪状态,超时≤1s),用net/http几行代码即可实现;部署时需确保探针超时小于periodSeconds、failureThreshold设为3–5、路径端口匹配且/livez避免写操作。

在 Go 应用中实现健康探针(Health Probe),核心是暴露一个轻量、快速响应的 HTTP 端点,供 kubernetes 或其他编排系统定期调用,以判断容器是否就绪(/readyz)或存活(/livez)。它不需复杂逻辑,但必须稳定、低延迟、不依赖外部故障点(如数据库连接失败不应直接导致 /livez 失败)。
区分 /livez 和 /readyz 的语义
Kubernetes 使用两个独立探针:liveness 探针失败会重启容器;readiness 探针失败则从服务端点中移除该实例。Go 服务中应明确分离二者职责:
- /livez:只检查进程自身是否卡死(如 goroutine 泄漏、死锁)、关键内部状态(如主事件循环是否运行)。避免访问数据库、redis、下游 HTTP 服务等。
- /readyz:可检查依赖服务是否就绪(如 DB 连接池可用、配置已加载、缓存预热完成),但超时要严格(建议 ≤1s),失败仅影响流量接入,不触发重启。
用标准 net/http 实现基础健康端点
无需额外框架,几行代码即可启动可靠探针:
http.HandleFunc("/livez", func(w http.ResponseWriter, r *http.Request) { // 检查基本运行状态(例如:主 goroutine 是否存活) select { case <-time.After(10 * time.Millisecond): w.WriteHeader(http.StatusOK) w.Write([]byte("ok")) default: w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("deadlock suspected")) } }) http.HandleFunc("/readyz", func(w http.ResponseWriter, r http.Request) { // 示例:检查数据库连接(带超时) ctx, cancel := context.WithTimeout(r.Context(), 500time.Millisecond) defer cancel() if err := db.PingContext(ctx); err != nil { http.Error(w, "db unreachable", http.StatusServiceUnavailable) return } w.WriteHeader(http.StatusOK) w.Write([]byte("ready")) })
使用第三方库简化管理(如 go-health)
当依赖项较多时,github.com/InVisionApp/go-health 提供了声明式注册和自动聚合能力:
立即学习“go语言免费学习笔记(深入)”;
- 定义多个检查器(DB、redis、HTTP 外部服务、自定义逻辑)
- 支持并行执行、超时控制、失败阈值
- 自动返回结构化 json(含各检查项状态、耗时、错误详情)
- 内置
/health/live和/health/ready路由,与 Kubernetes 探针无缝对接
示例片段:
h := health.New() h.AddReadinessCheck("db", health.CheckerFunc(func() error { return db.Ping() })) h.AddLivenessCheck("goroutines", health.CheckerFunc(func() error { if runtime.NumGoroutine() > 1000 { return errors.New("too many goroutines") } return nil })) http.Handle("/health/live", h.LiveHandler()) http.Handle("/health/ready", h.ReadyHandler())
部署时的关键注意事项
探针在生产中失效常因配置不当而非代码问题:
- 超时时间必须小于 probe period:K8s 默认 periodSeconds=10,timeoutSeconds 应设为 1–3 秒,否则探针堆积阻塞
- failureThreshold 不宜过小:设为 3–5 次连续失败再动作,避免网络抖动误判
- 路径和端口需与容器内服务一致:若 Go 服务监听 :8080,且健康端点是
/readyz,则 readinessProbe 需配port: 8080+path: /readyz - 避免在 /livez 中做写操作或加锁:防止探针请求引发竞态或阻塞主逻辑