fiber框架需手动实现健康检查端点,推荐分设/health/live和/health/ready:前者仅检查进程存活、goroutine数等本地状态,响应≤1秒;后者并行探测db、redis等依赖并缓存结果,失败返回503。

没有官方 HealthIndicator 机制,得自己搭端点 + 自定义逻辑。Fiber 是 Go 语言的轻量级 Web 框架,不像 Spring Boot 那样内置 HealthIndicator 接口和自动聚合能力。它的健康检查必须手动实现 HTTP 路由、状态判断、依赖探测和响应组装——好处是完全可控,坏处是容易漏掉关键维度或误判。
怎么暴露 /health 端点并返回基础状态
最简实现就是注册一个 GET 路由,返回固定 JSON:
app.Get("/health", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": "UP",
"timestamp": time.Now().UnixMilli(),
})
})
但这样只是“进程活着”,没检查任何依赖。实际要用时需注意:
- 别用
c.SendStatus(200)或纯字符串响应,K8s、云负载均衡通常要求 JSON body 含status字段且值为"UP"或"DOWN" - 路径别硬写
/health—— 如果服务有BasePath(比如/api/v1),健康端点必须匹配,否则云平台探针会 404 - 响应头建议加
Content-Type: application/json,虽然 Fiber 默认会设,但某些旧版 LB 对 header 敏感
如何检查数据库、Redis 等关键依赖
不能只看连接是否能建,得模拟一次最小可用操作:
- PostgreSQL/MySQL:执行
SELECT 1,设超时(如 2s),捕获context.DeadlineExceeded和连接错误 - Redis:用
client.Ping(ctx).Result(),不是Ping(ctx).Err()—— 后者可能返回nil但实际命令卡住 - HTTP 依赖服务(如下游 API):用带 timeout 的
http.Client发起 HEAD 或轻量 GET,避免触发业务逻辑
示例片段:
dbOK, dbErr := pingDB(ctx) // 自定义函数,内部用 context.WithTimeout
redisOK, redisErr := pingRedis(ctx)
status := "UP"
details := fiber.Map{"db": dbOK, "redis": redisOK}
if !dbOK || !redisOK {
status = "DOWN"
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"status": status,
"details": details,
})
为什么 readiness 和 liveness 要拆成两个端点
K8s 里混用同一个 /health 是高频翻车点:
-
livenessProbe失败 → Pod 被杀重启,适合查“进程卡死、goroutine 泄漏、死锁”这类不可恢复问题 -
readinessProbe失败 → 流量摘除,适合查“DB 连接池满、Redis 响应慢、配置未加载完”这类临时性问题 - 如果都指向同一端点,DB 一抖动就触发重启,新实例启动瞬间又抢连接,形成雪崩循环
推荐做法:
-
GET /health/live:只检查进程是否可响应、内存是否未 OOM、goroutine 数是否爆炸(runtime.NumGoroutine()> 5000 警告) -
GET /health/ready:检查 DB、Redis、下游 HTTP 服务、本地磁盘空间(statfs)、必要配置是否已加载
容易被忽略的细节和坑
真实生产环境里,这些点常导致探针误判或监控失灵:
- 没设超时:依赖服务 hang 住,整个
/health请求阻塞,K8s 探针超时后反复重试,压垮服务 - 没做缓存:每次请求都连 DB/Ping Redis,高频率探针(如每 5s 一次)变成 DoS 攻击
- 忽略 context 传递:goroutine 启动后没接收
c.Context(),导致请求取消时后台检查还在跑 - 健康响应体过大:加了太多 debug 信息(如堆栈、完整配置 dump),被 LB 截断或判定为异常响应
- 没配
startupProbe:冷启动慢的服务(如要加载大模型权重),直接上readinessProbe会导致启动失败被反复 kill
最终上线前,一定用 curl -v http://localhost:3000/health/ready 看状态码、body、耗时;再模拟依赖故障(如停掉 PostgreSQL),确认它真能切到 DOWN。健康检查不是“有就行”,而是“错不得”。











