必须自己写/health和/ready端点,fiber默认不提供健康路由;/health仅返回200 ok属“假就绪”,因未校验db、redis等真实依赖;/ready需用context超时调用pingcontext/ping/head等轻量检查,返回结构化json,并配自定义errorhandler确保只输出状态码。

必须自己写 /health 和 /ready 两个端点,Fiber 默认不提供任何健康路由,也不做依赖校验。
为什么 app.Get("/health", ...) 不够用
单纯返回 200 OK 的静态路由在 Kubernetes 中会被判定为“假就绪”:DB 连接池可能还没建好、Redis 网络已中断、下游服务正超时,但流量已经打进来,立刻触发 500。Istio 或 K8s 的 readinessProbe 只看 HTTP 状态码,不关心你有没有真连上依赖。
- 别用
c.SendString("ok")—— 它无法反映真实就绪状态 - 别在 handler 里调用
c.Next()—— 中间件可能篡改响应体或状态码 - 禁止用
recover()捕获 panic —— 探针需要明确失败信号,不是静默吞掉异常
怎么写带依赖校验的 /ready handler
核心是每个检查项必须带 context 超时、只发轻量请求、返回结构化 JSON。不要判断变量是否 nil,要验证连接是否真实可用。
- 数据库检查用
db.PingContext(ctx)(握手包),不用db.Query("SELECT 1") - Redis 检查用
redisClient.Ping(ctx).Result(),不是Get("dummy") - 外部 HTTP 服务优先用
http.Head(),设置ctx, cancel := context.WithTimeout(c.Context(), 2*time.Second) - 响应格式统一小写字段:
{"db": "ok", "redis": "timeout", "status": "degraded"}
app.Get("/ready", func(c fiber.Ctx) error {
ctx, cancel := context.WithTimeout(c.Context(), 2*time.Second)
defer cancel()
dbStatus := "ok"
if err := db.PingContext(ctx); err != nil {
dbStatus = "error"
}
redisStatus := "ok"
if err := redisClient.Ping(ctx).Err(); err != nil {
redisStatus = "error"
}
return c.JSON(fiber.Map{
"db": dbStatus,
"redis": redisStatus,
"status": mapStatus(dbStatus, redisStatus),
})
})
如何让探针对 Kubernetes 友好
Fiber 默认的 ErrorHandler 会把 panic 转成 HTML 页面,这对 curl -I 或 K8s 探针极不友好 —— 它只认状态码,HTML 响应体反而干扰监控解析。
- 初始化 Fiber 时必须传自定义
ErrorHandler:fiber.Config{ErrorHandler: func(c fiber.Ctx, err error) error { return c.Status(fiber.StatusInternalServerError).SendString("health check failed") }} - K8s 的
timeoutSeconds必须 ≤ handler 内部超时(比如你代码里设了 2s,K8s 就不能配 1s) -
failureThreshold建议 ≥ 3,避免网络抖动误判;periodSeconds推荐 5–10s,太密会压垮依赖
最常被忽略的是 handler 内部没设超时,或者用了阻塞式调用(比如没加 ctx 的 db.Ping()),导致整个探针 hang 住 —— 这会让 K8s 认定 Pod 不就绪,反复重试,最终拖垮整个服务发现链路。











