必须实现 health.healthbase 接口,使用官方 health.proto 和 grpc.health.checking 包;在 program.cs 中调用 addgrpchealthchecks() 和 mapgrpchealthchecks("/healthz");通过 ihealthcheckservice.setstatus 动态控制服务状态。

gRPC健康检查用哪个接口
必须实现 Health.HealthBase,这是 gRPC 官方健康检查协议定义的服务基类。它不是自定义接口,不能随便起名或改方法签名——否则客户端(比如 grpc_health_probe 或 Envoy)根本识别不了。
生成服务代码时,需确保 proto 文件是官方的 health.proto(来自 grpc/grpc),且引用的是 Grpc.Health.Checking NuGet 包(.NET 6+ 推荐)或 Grpc.AspNetCore.HealthChecks(旧版兼容用)。
如何注册 HealthService 到 ASP.NET Core Host
在 Program.cs 中,不能只 AddGrpc() 就完事;健康检查服务需要显式注册并启用中间件。
- 调用
services.AddGrpcHealthChecks()注册服务端逻辑 - 调用
app.MapGrpcHealthChecks("/healthz")暴露端点(路径可自定义,但必须是 gRPC endpoint,不是 HTTP GET) - 如果同时跑 HTTP 和 gRPC,确保 Kestrel 配置支持 HTTP/2(尤其开发时启用 TLS 或用
http://localhost:5001+"Http2UnencryptedSupport": true)
注意:MapGrpcHealthChecks 注册的是一个独立的 gRPC 服务,和你的业务 service 无关,它响应的是 HealthCheckRequest 并返回 HealthCheckResponse。
如何动态控制某个服务的健康状态
默认所有服务都返回 SERVING,但实际中常需根据依赖(DB、Redis、下游 gRPC)状态切换。得靠 IHealthCheckService 实例手动更新。
- 注入
IHealthCheckService(由AddGrpcHealthChecks()提供) - 用
healthCheckService.SetStatus("your-service-name", HealthStatus.NotServing)主动设为不健康 - 服务名必须和你在
Check请求里传入的service字段一致;空字符串对应整体状态 - 别在请求处理中频繁调用
SetStatus——它不是线程安全的写操作,建议配合后台轮询 + 状态缓存(如ConcurrentDictionary)
示例:DB 连接失败时,执行 healthCheckService.SetStatus("user-service", HealthStatus.NotServing),之后客户端查 Check(service: "user-service") 就会收到 NOT_SERVING。
常见连不通问题:客户端报 “UNAVAILABLE” 或 “failed to connect to all addresses”
这不是健康检查逻辑错了,而是底层连接失败。优先排查:
-
grpc_health_probe是否用了-tls-server-name(启用了 TLS 时必须指定) - Kestrel 是否监听了 HTTP/2 端口(
http/1.1协议无法承载 gRPC 健康检查) - 防火墙或 Istio/Envoy 是否拦截了非
/路径的 gRPC 流量(/healthz是合法路径,但某些代理默认只放行/) - 客户端是否用对了 scheme:
dns:///localhost:5001(非 TLS)或dns:///localhost:5001+--tls(TLS)
真正容易被忽略的是:健康检查服务本身不参与你的业务 service 的生命周期管理——哪怕你关掉所有业务 service,/healthz 仍可能返回 SERVING,除非你显式调用 SetStatus 修改。










