Health Primer
Health Primer
Section titled “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)什么时候从这里开始
Section titled “什么时候从这里开始”- 你正在定义或检查
HealthStatus或HealthState值 - 你正在为某个依赖(数据库、缓存、下游服务)实现
ComponentChecker - 你正在从多个 checker 构建
ComponentHealth聚合 - 你正在 readiness probe handler 中读写
ReadinessStatus
什么时候不该从这里开始
Section titled “什么时候不该从这里开始”- 改动关于暴露 health 的 HTTP 端点 — 那属于服务自身的 handler 层
- 改动引入了检查编排、重试策略或 health manager 抽象
- 工作关于 build metadata 暴露、health 历史记录保留或趋势报告
- 改动添加了 metrics、分析或导出后端 — 那些属于
x/observability
当前仓库里先读哪些文件
Section titled “当前仓库里先读哪些文件”health/module.yamlhealth/core.gohealth/readiness.goreference/standard-service/internal/handler/health.go
更具体的归属例子
Section titled “更具体的归属例子”这些工作适合留在 health | 一旦变成这些问题就应移出 |
|---|---|
HealthStatus — 类型枚举:Healthy、Degraded、Unhealthy | 带有领域词汇的特定功能状态目录 |
ComponentChecker 接口与 ComponentHealth 聚合 | 按计划执行检查并带有重试的 health manager |
ReadinessStatus — 用于 readiness probe 的小型显式类型 | HTTP 端点 wiring、传输特定的响应格式化 |
| 在 handler 内部检查单个组件的状态 | 运维报告、health 历史导出或趋势分析 |
import "github.com/spcent/plumego/health"Liveness 与 Readiness 处理器
Section titled “Liveness 与 Readiness 处理器”规范模式是在 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)}实现 ComponentChecker
Section titled “实现 ComponentChecker”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)}HealthState 常量
Section titled “HealthState 常量”| 常量 | 含义 | 能否接收流量 |
|---|---|---|
health.StatusHealthy | 所有系统正常 | 是 |
health.StatusDegraded | 部分故障,服务降级 | 是 |
health.StatusUnhealthy | 组件宕机,无法提供服务 | 否 |
state := health.StatusDegradedif state.IsReady() { // 服务可以接收流量}注册 health 路由
Section titled “注册 health 路由”healthH := handler.HealthHandler{ ServiceName: "my-service", db: DBChecker{db: sqlDB},}app.Get("/healthz", http.HandlerFunc(healthH.Live))app.Get("/readyz", http.HandlerFunc(healthH.Ready))为什么单独写这一页
Section titled “为什么单独写这一页”health 是支持包,不是 feature catalog。服务经常混淆”表示 health 的类型”与”管理并暴露 health 的系统”。将 health 保持为纯类型和 checker,意味着无论 health 是通过 HTTP、gRPC 还是 metrics scrape 端点暴露,都可以使用同一个模型 — 格式不是模型的关注点。
- core API 快速参考 —
App.Prepare、App.Server和生命周期签名 - 健康检查指南
- Core Primer
- Metrics Primer
- 参考应用