健康检查接口应显式返回200或503状态码,避免依赖默认200;响应体极简JSON如{"status":"ok","timestamp":1717023456};/healthz仅检查进程存活,/readyz检查依赖服务并超时控制。

健康检查接口该返回什么状态码
Beego 默认的 Controller 不会自动处理 HTTP 状态码语义,健康检查必须显式返回 200 或 503,不能依赖默认 200。返回 404、500 或空响应体都可能被负载均衡器或 Kubernetes 的 livenessProbe 误判为异常。
实操建议:
- 用
this.Ctx.ResponseWriter.WriteHeader(http.StatusOK)显式设状态码,避免依赖this.Data["json"]自动触发的 200 - 响应体保持极简:纯 JSON
{"status": "ok", "timestamp": 1717023456},不嵌套业务字段 - Kubernetes 场景下,
readinessProbe和livenessProbe均应指向同一接口,但逻辑可分离(见下节)
如何区分 readiness 和 liveness 检查逻辑
Beego 没有内置 readiness/liveness 分离机制,靠路由和手动判断。硬编码两个接口(如 /healthz 和 /readyz)最直接,也最易被运维识别。
实操建议:
- 在
router.go中注册两条独立路由:beego.Router("/healthz", &HealthController{}, "get:Health")和beego.Router("/readyz", &HealthController{}, "get:Ready") -
Health()方法只检查自身进程存活(如能响应、goroutine 数未超限),不做 DB 或 Redis 连通性校验 -
Ready()方法才检查依赖服务,例如用net.DialTimeout("tcp", "redis:6379", 2*time.Second),失败则返回503 - 避免在
Ready()中调用耗时 DB 查询;改用连接池Ping(),并设context.WithTimeout
Beego v2.x 中使用 context.Context 控制超时
v2.x 支持 this.Ctx.Request.Context(),但健康检查接口通常不走完整中间件链,容易忽略上下文取消。若依赖服务响应慢,整个 probe 会卡住,触发容器重启。
实操建议:
- 不要直接用
http.DefaultClient,构造带超时的 client:client := &http.Client{Timeout: 3 * time.Second} - 对 DB 检查,用
sql.DB.PingContext(ctx)而非Ping(),把this.Ctx.Request.Context()传进去 - 若检查逻辑含多个并行依赖,用
errgroup.WithContext统一管控,任一失败即中止 - 注意 Beego 的
ctx.Input.SetData()不影响 HTTP 请求上下文,别混淆
日志和监控埋点怎么加才不影响性能
健康检查每秒可能被调用数十次,打全量日志或上报 metrics 会导致 I/O 拖累主线程。Beego 的 logs.Info() 默认同步写磁盘,高频率下易成瓶颈。
实操建议:
- 健康检查接口内禁用
logs.Info(),仅在出错时用logs.Warn()记录一次(如 Redis 连接失败) - 指标上报走异步通道:定义
var healthMetricCh = make(chan HealthMetric, 100),在 goroutine 中消费,主逻辑只发消息 - 避免在检查逻辑中调用
time.Now().UnixNano()多次,提取一次复用 - 如果用了 Prometheus,用
promhttp.Handler()单独挂 /metrics 路由,别塞进健康接口里
健康检查看似简单,真正上线后最常出问题的是超时控制粒度和依赖服务的错误传播——比如 Redis 临时抖动导致所有 readyz 返回 503,进而触发滚动重启。留好 context 透传和快速失败路径,比堆功能重要得多。


















