Skip to content
bitzorcas
中EN

Concept

健康检查

区分 liveness、readiness、配置自洽与真实依赖连通性,并正确接入 Kubernetes 与 Aspire。

Last updated

健康检查回答两个不同问题:进程是否还活着,以及这个实例现在能否接收流量。把数据库检查放进 liveness 会在依赖抖动时制造重启风暴;把所有检查都写成 Healthy 又会把故障实例留在负载均衡池里。

进程失活依赖未就绪恢复

编排器

/health/live

/health/ready

重启实例

摘除流量

重新入池

四个端点

端点过滤条件用途Degraded/Unhealthy
/health/livelive 标签进程存活编排器可重启实例
/health/readyready 标签基础依赖与接收控制面流量的就绪明确映射为 503
/health/licenselicense 标签商业许可状态明确映射为 503
/health全部检查聚合与人工诊断使用框架默认映射

四个端点当前都允许匿名访问。默认响应不会输出连接串或 License payload,但生产入口仍应限制来源、请求频率和可见范围。

Liveness

AddServiceDefaults() 注册一个不访问外部依赖的 self 检查:

// ① 先看契约与控制流;校验、取消和类型化错误都要显式保留。
services.AddHealthChecks()
.AddCheck(
"self",
() => HealthCheckResult.Healthy("alive"),
tags: [ServiceDefaultsExtensions.LivenessTag]);

只要进程能处理请求,liveness 就应成功。数据库、RabbitMQ、Redis 或第三方 API 失败不应直接触发 Pod 重启。

Readiness 的两层证据

API Host 的基础 readiness 同时检查配置自洽与实际依赖。License 使用独立 license 标签,不进入 ready:尚未签发 License 时,登录、密码恢复、导航和 LicenseManagement 控制面仍能接收流量;普通业务消息仍由许可管线失败关闭。

配置与 DI 自洽

RuntimeDependencyReadinessHealthCheck 验证:

  • 数据库与 RabbitMQ 是否成对配置,以满足 CAP Outbox 运行模式;
  • 配置了 Redis 时是否注册连接复用器;
  • MinIO 模式是否具备 endpoint、access key 和 secret key;
  • Webhook delivery 开启时,IP allowlist、限流参数和 Redis limiter 是否就绪。

API Shell 可以有意不配置数据库、RabbitMQ 和 Redis,并报告 Healthy。生产部署不能把 Shell 模式的 Healthy 当作完整业务就绪证据。

实际连通性

进入持久化模式后,组合根额外注册:

  • database-connectivity:打开 Provider 连接并检查状态;
  • rabbitmq-connectivity:以三秒超时探测 AMQP TCP 端口;
  • 缓存、S3 和 Webhook delivery 等 Adapter 自己的窄检查;License 另由 /health/license 暴露。

数据库与 RabbitMQ 短暂失败当前返回 Degraded,而 /health/ready 把 Degraded 映射为 503。因此实例会退出流量池,但不会因 liveness 失败被反复重启。

Kubernetes 配置

# ① 示例值应由受控配置替换,不能提交生产 Secret。
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
# ② Readiness 失败会摘除流量,但不应触发无休止重启。
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3

启动耗时较长时使用 startupProbe,不要单纯把 liveness 的失败阈值调得很大。探针超时要大于单个健康检查的合理上限,又不能长到故障实例持续接流量。

新增检查

健康检查应归属于拥有该依赖的 Adapter:

[RegisterHealthCheck("search-connectivity", "ready", "search")]
public sealed class SearchConnectivityHealthCheck : IHealthCheck
{
// ① 注册属性把探针纳入生成的健康检查目录并附加 ready/search 标签。
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
// ② 只执行有超时、无敏感输出的窄探针,不能跑完整业务查询。
}
}

API Host 当前通过 [RegisterHealthCheck] 在组合根扫描已加载的 BitzOrcas* 程序集;数据库和 RabbitMQ 等条件检查由显式注册保留运行模式语义。这是 Host 层现有的受限反射路径,不应被复制到 Framework 或业务模块。

检查实现要满足:

  • 使用取消令牌和短超时;
  • 不做 schema migration、seed、写入或修复;
  • 不返回密码、连接串、token 或内部异常细节;
  • 名称稳定,标签明确;
  • 区分配置错误、依赖暂时不可达和业务数据异常。

常见误区

  • readiness 只注册 self,因此永远 Healthy;
  • liveness 查询数据库,网络闪断就重启所有实例;
  • 生产仍以 API Shell 模式启动,却把 Healthy 宣称为业务就绪;
  • 健康检查调用昂贵业务查询或外部写操作;
  • 所有实例同时高频探测下游,反而加重故障。

发布验收

发布前要分别保存 live、ready、license 和完整 health 的响应证据,并在受控环境阻断数据库、RabbitMQ、Redis 或对象存储连接,确认 readiness 摘流而 liveness 仍存活。随后恢复依赖,验证实例能自动重新进入流量池。

还要验证 License 不可用时 /health/ready 仍能表达基础运行就绪而 /health/license 与聚合 /health 返回 503、普通业务仍被拒绝、Shell 模式不会被误当成生产就绪、匿名探针受到入口限流和网络策略保护,以及响应正文不包含连接或 License 内容。只有正常态截图不能证明故障语义。

相关

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%