健康检查回答两个不同问题:进程是否还活着,以及这个实例现在能否接收流量。把数据库检查放进 liveness 会在依赖抖动时制造重启风暴;把所有检查都写成 Healthy 又会把故障实例留在负载均衡池里。
四个端点
| 端点 | 过滤条件 | 用途 | Degraded/Unhealthy |
|---|---|---|---|
/health/live | live 标签 | 进程存活 | 编排器可重启实例 |
/health/ready | ready 标签 | 基础依赖与接收控制面流量的就绪 | 明确映射为 503 |
/health/license | license 标签 | 商业许可状态 | 明确映射为 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 内容。只有正常态截图不能证明故障语义。