/healthz必须绕过中间件链,因k8s livenessprobe高频调用(默认每秒1次),若经jwt鉴权、日志等中间件,易因401或耗时导致误判重启;/readyz需检查db连接池、grpc状态等强依赖并设≤100ms超时,避免弱依赖(如redis)影响就绪判定。

GoLand 项目里写 /healthz 和 /readyz 探针接口,不是加两个路由就完事——K8s 的 liveness/readiness probe 会频繁发起请求,而默认 Gin/Echo 的中间件、日志、鉴权等逻辑若未剥离,会导致探针误判或拖慢集群调度。
为什么 /healthz 必须绕过中间件链
K8s 的 livenessProbe 默认每秒调用一次 /healthz,如果这个端点走了完整 HTTP 中间件(比如 JWT 鉴权、请求日志、OpenTelemetry trace 注入),不仅增加不必要的 CPU/内存开销,还可能因鉴权失败返回 401 导致 Pod 被反复重启。
- 直接注册到路由引擎最外层,不经过任何中间件:Gin 用
r.NoRoute()前的独立r.GET("/healthz", ...);Echo 用e.GET("/healthz", ...)并确保没套middleware.JWT()等全局中间件 - 避免依赖外部服务:不查数据库、不调下游 API、不读配置文件(
viper.Get()可能触发文件监听或远程 etcd 拉取) - 返回必须是 200 + 纯文本或空 body:
curl -I http://localhost:8080/healthz应看到HTTP/1.1 200 OK,不能有 JSON 包裹或额外 header
/readyz 要检查哪些真实依赖
/readyz 是 K8s 的 readiness probe 目标,它决定是否把流量导入该 Pod。它需要反映“业务是否真正可服务”,但又不能太重——比如检查 MySQL 连接池是否 ready 比检查 MySQL 是否 ping 通更合理,因为连接池耗尽时 ping 得通但实际无法处理请求。
GoLand 2026.1.1 是 2026.1 发布后的首个维护修正版本,适合已经开始体验 2026.1 新功能并希望同步补丁的开发者。它更适合用于入门项目、现有项目迁移测试和 IDE 行为验证。
- 只检查**当前 Pod 内部状态**和**强依赖组件**:如 gRPC client 连接状态、本地缓存初始化完成、消息队列消费者是否已启动
- 跳过弱依赖:Redis 缓存不可用时,业务可能降级走 DB,
/readyz不应因此返回 500 - 超时必须严格控制:整个 handler 执行时间建议 ≤ 100ms,否则 K8s 会判定超时并摘除实例;可用
context.WithTimeout(ctx, 100*time.Millisecond)包裹检查逻辑 - 示例结构(Gin):
func checkDBReady() error {
db := getDBInstance() // 从全局变量或 DI 容器取,非新建连接
if err := db.Ping(); err != nil {
return fmt.Errorf("db ping failed: %w", err)
}
// 额外检查连接池是否非空
if db.Stats().OpenConnections == 0 {
return errors.New("db connection pool empty")
}
return nil
}
GoLand 里如何快速生成并验证探针路由
在 GoLand 中手写探针接口容易漏掉 K8s 要求的细节,比如缺少 Content-Type: text/plain 或误用了结构体返回。利用 IDE 的能力可以规避低级错误。
- 右键点击
main.go→ Generate → HTTP Handler(需安装HTTP Client插件),输入/healthz自动生成空白 handler,再手动删掉中间件装饰 - 在
go.mod中确认已启用模块模式:GO111MODULE=on,否则viper等依赖可能加载失败导致/readyzpanic - 本地验证命令别用
curl就完事:运行kubectl run --rm -i --tty debug --image=busybox -- sh进入集群内环境,执行wget --spider -q http://your-service:8080/readyz || echo "fail",模拟 K8s probe 行为 - 注意 GoLand 的 Debug 配置:Run Configurations 中勾选
Allow running in parallel,否则热重载时探针请求可能被阻塞
真正容易被忽略的是:探针接口的 HTTP 方法必须是 GET,且不能要求 TLS(K8s probe 默认不带证书),哪怕你的主服务启用了 HTTPS,也要在 Ingress 或 Service 层做协议终止,让 /healthz 走明文 HTTP 流量——否则 readiness 会永远 pending。










