健康检查路由必须用GET且不带body,返回200状态码;区分liveness与readiness语义;避免中间件拦截;禁止阻塞操作与body解析。

健康检查路由必须用 GET 且不带 body
Gin 中暴露 /healthz 或 /readyz 这类 Kubernetes 健康检查端点时,Kubernetes 的 kubelet 默认以 HTTP GET 请求调用,且不发送任何请求体(body)。如果误用 POST 或依赖 c.ShouldBindJSON() 等解析 body 的逻辑,会导致 400 错误或超时失败。
实操建议:
- 始终用
router.GET("/healthz", healthHandler),不要用POST或ANY - handler 函数内禁止调用
c.Bind()、c.ShouldBind()等可能阻塞或报错的解析方法 - 返回状态码必须是 200,响应体建议为空或仅含简单字符串(如
"ok"),避免 JSON 序列化开销
handler 里不能有阻塞或长耗时操作
Kubernetes 的探针默认超时为 1 秒(livenessProbe timeoutSeconds: 1),且重试间隔短。若 handler 中执行数据库 ping、HTTP 外部调用、锁竞争或未加 context 超时的 goroutine,极易触发探针失败并导致 Pod 被重启。
实操建议:
- 健康检查只做内存态判断:例如检查本地
atomic.Value标记的服务就绪状态 - 若需验证下游依赖(如 DB),应使用预热后的连接池 +
context.WithTimeout(c.Request.Context(), 300*time.Millisecond) - 避免在 handler 中启动新 goroutine;如必须异步,确保不阻塞主流程,且错误不 panic
区分 liveness 和 readiness 的路由与语义
Kubernetes 要求 livenessProbe 和 readinessProbe 可指向不同路径或同一路径但行为不同。Gin 本身不区分,需靠路由设计或 handler 内部逻辑识别。常见错误是共用一个 /healthz 却混用恢复性逻辑(比如 readiness 失败应拒绝流量,liveness 失败应重启容器)。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
实操建议:
- 推荐显式分离:用
router.GET("/healthz", livenessHandler)和router.GET("/readyz", readinessHandler) - 若复用单一路由(如都走
/healthz),可通过 query 参数区分:/healthz?probe=liveness,但需在 handler 中解析c.Query("probe") -
livenessHandler应只检查进程是否存活(如能否响应 HTTP);readinessHandler可检查依赖就绪(如 DB 连接池非空、配置加载完成)
注意 Gin 中间件对健康检查的干扰
很多项目全局注册了鉴权、日志、CORS 等中间件,而 Kubernetes 探针请求无 token、无 Origin 头,容易被拦截。典型现象是 /healthz 返回 401 或 403,Pod 一直卡在 CrashLoopBackOff。
实操建议:
- 用
router.NoRoute()或router.Use()之前单独挂载健康路由:router := gin.New() router.GET("/healthz", healthHandler) router.GET("/readyz", readyHandler) // 再挂其他中间件 router.Use(authMiddleware(), loggingMiddleware()) - 或者用
gin.RouterGroup隔离:health := router.Group("") health.GET("/healthz", healthHandler) health.GET("/readyz", readyHandler)再对主 group 加中间件 - 禁用日志中间件对健康路径的记录(避免刷屏),可用路径前缀过滤:
if !strings.HasPrefix(c.Request.URL.Path, "/health") { logRequest() }
Gin 做健康检查本身很简单,真正容易出问题的是它和 Kubernetes 探针模型之间的隐含契约:无 body、低延迟、无副作用、不被中间件劫持。漏掉其中任一环,都会让 Pod 在集群里“假装活着”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










