跳转到内容

Health Primer

当你已经通过 稳定根 确认改动仍属于默认服务路径,而且问题进一步收窄到服务如何汇报自身健康状态时,就打开这一页:哪些类型描述 liveness 与 readiness、各组件如何表示自身状态,以及规范的 health 模型是什么样的。

health 拥有 health status 类型、readiness 助手和组件健康模型。它有意不是 HTTP 包,也不是运维分析包。HTTP health 端点属于服务自身的 handler 层;编排逻辑属于参考应用或扩展族。

checker := health.ComponentCheckerFunc(func(ctx context.Context) health.HealthState {
if err := db.PingContext(ctx); err != nil {
return health.StateUnhealthy
}
return health.StateHealthy
})
agg := health.NewAggregate(checker)
  • 你正在定义或检查 HealthStatusHealthState
  • 你正在为某个依赖(数据库、缓存、下游服务)实现 ComponentChecker
  • 你正在从多个 checker 构建 ComponentHealth 聚合
  • 你正在 readiness probe handler 中读写 ReadinessStatus
  • 改动关于暴露 health 的 HTTP 端点 — 那属于服务自身的 handler 层
  • 改动引入了检查编排、重试策略或 health manager 抽象
  • 工作关于 build metadata 暴露、health 历史记录保留或趋势报告
  • 改动添加了 metrics、分析或导出后端 — 那些属于 x/observability
  1. health/module.yaml
  2. health/core.go
  3. health/readiness.go
  4. reference/standard-service/internal/handler/health.go
这些工作适合留在 health一旦变成这些问题就应移出
HealthStatus — 类型枚举:HealthyDegradedUnhealthy带有领域词汇的特定功能状态目录
ComponentChecker 接口与 ComponentHealth 聚合按计划执行检查并带有重试的 health manager
ReadinessStatus — 用于 readiness probe 的小型显式类型HTTP 端点 wiring、传输特定的响应格式化
在 handler 内部检查单个组件的状态运维报告、health 历史导出或趋势分析
import "github.com/spcent/plumego/health"

规范模式是在 handler 层暴露 /healthz(liveness)和 /readyz(readiness),并用 health 类型对状态建模:

type HealthHandler struct {
ServiceName string
db health.ComponentChecker
}
func (h HealthHandler) Live(w http.ResponseWriter, r *http.Request) {
contract.WriteResponse(w, r, http.StatusOK, map[string]string{
"status": "ok",
"service": h.ServiceName,
}, nil)
}
func (h HealthHandler) Ready(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
status := health.ReadinessStatus{
Ready: true,
Timestamp: time.Now(),
Components: map[string]bool{},
}
if err := h.db.Check(ctx); err != nil {
status.Ready = false
status.Reason = "database unavailable"
status.Components["db"] = false
contract.WriteResponse(w, r, http.StatusServiceUnavailable, status, nil)
return
}
status.Components["db"] = true
contract.WriteResponse(w, r, http.StatusOK, status, nil)
}
type DBChecker struct {
db *sql.DB
}
func (c DBChecker) Name() string { return "database" }
func (c DBChecker) Check(ctx context.Context) error {
return c.db.PingContext(ctx)
}
常量含义能否接收流量
health.StatusHealthy所有系统正常
health.StatusDegraded部分故障,服务降级
health.StatusUnhealthy组件宕机,无法提供服务
state := health.StatusDegraded
if state.IsReady() {
// 服务可以接收流量
}
healthH := handler.HealthHandler{
ServiceName: "my-service",
db: DBChecker{db: sqlDB},
}
app.Get("/healthz", http.HandlerFunc(healthH.Live))
app.Get("/readyz", http.HandlerFunc(healthH.Ready))

health 是支持包,不是 feature catalog。服务经常混淆”表示 health 的类型”与”管理并暴露 health 的系统”。将 health 保持为纯类型和 checker,意味着无论 health 是通过 HTTP、gRPC 还是 metrics scrape 端点暴露,都可以使用同一个模型 — 格式不是模型的关注点。