Go服务健康检查应使用标准库http.ServeMux+http.HandlerFunc实现,返回200 OK及轻量响应(如"ok"或最小JSON),/healthz和/readyz需分离,绕过中间件,依赖探活须设超时并降级,避免第三方库。

Go 服务的健康检查不需要额外组件,用标准库 http.ServeMux + http.HandlerFunc 就能可靠实现,关键在状态定义、响应格式和路由隔离。
健康检查接口该返回什么状态码和 body
HTTP 健康检查不是“有没有 panic”,而是“能不能服务”。Kubernetes、Consul、Nginx 等只认 200 OK 为健康;非 2xx(尤其是 503 Service Unavailable)会被判定为不健康。body 不强制要求 JSON,但必须轻量、无副作用、不触发业务逻辑。
- 推荐返回纯文本
"ok"或最小化 JSON:{"status":"up","timestamp":1717023456} - 避免返回数据库连接详情、配置内容等敏感信息
- 不要在 handler 中调用
os.Exit(1)或修改全局状态——这会中断整个进程 - 若需区分就绪(ready)与存活(live),应拆成两个独立 endpoint,如
/healthz(liveness)和/readyz(readiness)
如何避免健康检查被中间件干扰
很多项目用 gorilla/mux 或自定义中间件(日志、鉴权、CORS),但健康检查必须绕过它们——否则一个鉴权失败会导致整个服务被下线。
- 用独立的
http.ServeMux实例注册健康路由,再通过http.Serve单独监听(如:8081) - 或在主 mux 中用
HandleFunc("/healthz", ...)直接注册,不经过任何中间件链 - 切勿把健康 handler 包进
authMiddleware(handler)或类似包装器里 - 验证方式:用
curl -v http://localhost:8080/healthz,确认响应头中没有X-Request-ID、WWW-Authenticate等业务中间件注入字段
是否需要做依赖探活(DB、Redis、下游 HTTP)
取决于部署场景。Kubernetes liveness probe 一般不做依赖检查——它只保证进程活着;readiness probe 才适合加 DB 连通性,但必须加超时和降级。
立即学习“go语言免费学习笔记(深入)”;
- DB 检查用
db.PingContext(ctx),且ctx必须带time.Second * 2超时,防止卡住整个 probe - Redis 用
client.Ping(ctx).Err(),同样限时 - 下游 HTTP 服务检查建议禁用——它引入了级联故障风险;改用本地状态(如“最近 1 分钟是否有成功请求”)更稳
- 所有依赖检查失败时,仍返回
503,但 body 明确标注失败项,例如:{"status":"down","failed_check":"redis"}
为什么不用第三方 health check 库(如 uber-go/zap 的 health 或 go-health)
这些库多数增加了抽象层,却没解决核心问题,反而带来隐含行为:
-
go-health默认启用 metrics 上报,会悄悄启动 goroutine 和定时 flush,线上环境容易遗漏清理 - 部分库把健康状态存在内存 map 里,多实例部署时无法反映真实集群状态
- 它们往往强制要求 JSON 响应、特定字段名,和运维系统(如 Envoy 的 /server_info)不兼容
- 真正需要的只是几行可审计、可调试、无外部依赖的代码 —— 下面这个就是全部:
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}复杂点在于你是否真需要依赖探测,以及能否控制好它的超时和失败传播范围——而不是选哪个“组件”。


















