gRPC健康检查用哪个接口
必须实现
Health.HealthBase,这是 gRPC 官方健康检查协议定义的服务基类。它不是自定义接口,不能随便起名或改方法签名——否则客户端(比如
grpc_health_probe或 Envoy)根本识别不了。
生成服务代码时,需确保 proto 文件是官方的
health.proto(来自 grpc/grpc),且引用的是
Grpc.Health.CheckingNuGet 包(.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修改。
