grpc-gateway 怎么给接口注册 /healthz 健康检查端点并接入 gRPC 健康检查协议?
【免费下载链接】grpc-gatewaygRPC to JSON proxy generator following the gRPC HTTP spec项目地址: https://gitcode.com/GitHub_Trending/gr/grpc-gateway
如果你的 gRPC 服务前面挂了一个 grpc-gateway,负载均衡器或容器编排需要探测整体健康状态,你需要做两件事:在 gRPC 服务端实现 gRPC Health Checking Protocol(Watch和Check两个方法),再在 gateway 的runtime.ServeMux上注册/healthz端点,让 HTTP 探测请求被转发到 gRPC 服务端的Check方法。这样/healthz反映的是整个后端系统的真实健康状态,而不只是 gateway 进程活着。本文按 Health check 文档 和 runtime/mux.go 的源码给出这条操作路径。
一、在 gRPC 服务端接入 gRPC Health Checking Protocol
要使用 gRPC 健康检查协议,服务必须实现Watch和Check两个方法。
1. 注册 health server
在你的 gRPC server 初始化代码里:
- 引入
google.golang.org/grpc/health/grpc_health_v1包; - 用
grpc_health_v1.RegisterHealthServer(grpcServer, yourService)把 health server 注册到你的grpc.Server上,其中yourService是实现了下面两个方法的结构体。
2. 实现 Check 与 Watch 方法
文档给出的最小实现如下:
Check 方法:
func (s *serviceServer) Check(ctx context.Context, in *health.HealthCheckRequest) (*health.HealthCheckResponse, error) { return &health.HealthCheckResponse{Status: health.HealthCheckResponse_SERVING}, nil }Watch 方法。文档示例只注册方法而不真正实现流式检查,返回Unimplemented:
func (s *serviceServer) Watch(in *health.HealthCheckRequest, _ health.Health_WatchServer) error { // Example of how to register both methods but only implement the Check method. return status.Error(codes.Unimplemented, "unimplemented") }如果你的服务端实现了多个服务,Check方法里可以根据HealthCheckRequest的Service属性写自己的判定逻辑——这正是后文?service=查询参数会送达的字段。
二、给 gateway 的 ServeMux 注册 /healthz 端点
gateway 侧用ServeMuxOptionWithHealthzEndpoint自动注册/healthz端点,它的参数是你对已注册 gRPC 服务的连接(源码签名见 runtime/mux.go:WithHealthzEndpoint(healthCheckClient grpc_health_v1.HealthClient),即从*grpc.ClientConn得到的 health client):
// 对 gRPC 服务建立连接后 healthClient := grpc_health_v1.NewHealthClient(conn) mux := gwruntime.NewServeMux( gwruntime.WithHealthzEndpoint(healthClient), )端点的工作方式(源码 runtime/mux.go):
- 只处理
GET请求,收到请求后调用 gRPC 端grpc.health.v1.Health/Check; - URL 中的
?service=<service>查询参数会被原样放入HealthCheckRequest.Service字段,用于定向探测某个具体服务; - 返回
SERVING时,用请求的出站 marshaler 把Check响应以Content-Type: application/json写出; - 非
SERVING时按状态映射错误:NOT_SERVING/UNKNOWN返回503 Unavailable,SERVICE_UNKNOWN返回404 NotFound。
可选:用自定义路径注册健康端点
如果不想要固定的/healthz路径,用WithHealthEndpointAt(healthCheckClient, endpointPath),它接收同一个 gRPC 连接参数加一个自定义endpointPath string,行为与WithHealthzEndpoint相同,只是路径可指定(即等价于WithHealthEndpointAt(client, "/healthz")的一般形式)。
三、验证
gRPC 侧:文档建议用 grpc-health-probe 工具(grpc-ecosystem 出品的命令行探针)直接对 gRPC 服务做健康检查,确认Check方法已经可用。
HTTP 侧:对 gateway 发GET /healthz。
如果 gRPC 服务端没有实现健康检查协议,每次请求都会得到文档中给出的这个响应:
{"code":12,"message":"unknown service grpc.health.v1.Health","details":[]}看到这个
code:12(unimplemented)说明 gateway 转发链路是通的,但服务端缺少 health 方法,回去检查RegisterHealthServer是否注册成功。如果服务端已实现且状态为
SERVING,/healthz返回Check响应的 JSON 编码结果;服务不在服务状态时返回上节所述的 503/404。多服务场景下,用
GET /healthz?service=<service>定向探测,<service>的值会出现在Check收到的请求里,供你的判定逻辑使用。
限制与说明
/healthz本身不判断任何状态,它只是把请求转发给Check方法;探测结果完全取决于你在 gRPC 服务端的实现。上例代码直接返回SERVING,生产实现应接入真实的就绪判定。- 仓库示例 gateway(examples/internal/gateway/handlers.go)用的是另一种手写方案:不依赖健康检查协议,而是检查 gRPC 连接状态,
Ready时返回ok,否则返回 502。如果你的 gRPC 服务无法改造来实现健康检查协议,可以参考这个文件,但它与本文的WithHealthzEndpoint主路径是两条独立方案,不要混用。 - 完整的端点行为细节以 runtime/mux.go 中
WithHealthEndpointAt的源码为准。
【免费下载链接】grpc-gatewaygRPC to JSON proxy generator following the gRPC HTTP spec项目地址: https://gitcode.com/GitHub_Trending/gr/grpc-gateway
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考