HealthCheckService 和 IHealthChecksBuilder 怎么用
ASP.NET Core 的健康检查不是靠手动轮询或写个
GET /health就完事的,它依赖内置的
HealthCheckService后台服务和
IHealthChecksBuilder注册机制。你得先在
Program.cs里调用
AddHealthChecks(),它返回的就是
IHealthChecksBuilder实例,所有检查项都通过它添加。
常见错误是直接 new 一个自定义类然后塞进 DI 容器,结果健康端点返回始终是
Healthy或直接 500——因为没走健康检查管道,
HealthCheckService根本不知道它存在。 必须用
services.AddHealthChecks().AddCheck<mydbhealthcheck>("db")</mydbhealthcheck>,不能只注册 MyDbHealthCheck类型 自定义检查类必须实现
IHealthCheck接口,且
CheckHealthAsync方法不能抛未捕获异常(会转成
Unhealthy,但堆栈不返回给客户端) 如果检查逻辑含异步 IO(如数据库连接测试),必须用
await,别用
.Result或
.Wait(),否则可能死锁
如何添加 HTTP 端点并控制响应格式
注册完检查项后,还得暴露一个可访问的 endpoint,靠的是
MapHealthChecks扩展方法。它默认返回 JSON,但字段精简(只有
status、
results),不包含耗时、异常详情等调试信息。
开发阶段常需要看到每个检查项的执行时间或失败原因,这时得启用
ResponseWriter自定义输出逻辑,而不是改用第三方中间件拦截响应体。
app.MapHealthChecks("/health", new HealthCheckOptions { ResponseWriter = WriteDetailedHealthResponse })
WriteDetailedHealthResponse是个委托,接收
HttpContext和
HealthReport,可序列化
report.Entries中每个
HealthReportEntry的
Exception、
Duration属性 生产环境禁用详细输出,避免泄露内部信息;可用
Environment.IsDevelopment()控制开关
数据库连接健康检查为什么总是 Healthy 即使连不上
用
AddSqlServer、
AddNpgsql等扩展方法时,默认只检查连接字符串能否解析,不真连数据库。这是为了性能——健康检查端点不该成为 DB 连接风暴源头。
真正验证连通性,得传入
configureOptions参数,开启
includeEntityFramework或显式调用
Open()+
Close()。 SQL Server:
.AddSqlServer(connectionString, healthQuery: "SELECT 1", name: "sql")——
healthQuery是关键,不设就只是解析连接字符串 EF Core 场景下,若用了
AddDbContextHealthCheck<appdbcontext></appdbcontext>,它默认会调用
context.Database.CanConnectAsync(),但前提是上下文已正确注册且无作用域问题 注意连接超时:健康检查默认超时 30 秒,可通过
timeout参数缩短,比如
timeout: TimeSpan.FromSeconds(5)
多个健康检查并发执行时状态怎么聚合
默认策略是「任意一项 Unhealthy → 整体 Unhealthy」,由
HealthReport.Status的计算逻辑决定。这个聚合行为不可配置,但你可以用
RequireHealthy或
RequireHealthyExcept分组控制依赖关系。
比如缓存服务挂了不影响主流程,但数据库挂了必须告警,这时就得拆成两个 endpoint,而不是塞进同一个检查组。
用AddCheck注册的每一项独立执行,彼此不阻塞;
HealthCheckService并发运行它们(非顺序) 想让某些检查仅在其他检查 Healthy 时才运行?不行——框架不支持条件触发,需在
CheckHealthAsync内部手动判断并返回
HealthCheckResult.Degraded()或跳过逻辑 聚合结果中的
HealthReport.TotalDuration是所有检查最大耗时,不是总和;单个检查若超时,会被取消并标记为
Unhealthy
最易忽略的一点:健康检查中间件在请求管道的位置。它必须放在
UseRouting之后、
UseEndpoints之前,否则
MapHealthChecks不生效。顺序错,/health 就 404。
