gRPC 定义了一个健康检查协议(Health Checking API),它允许 gRPC服务暴露服务器的状态,这样消费者就能探查服务器的健康信息。服务器的健康情况是由服务器是否响应非健康状态来确定的,当服务器还没有准备好处理 RPC 或者根本没有响应健康探针的请求时,就会发生这种情况。如果响应表明服务器处于非健康状态或者在规定的时间窗口内没有收到响应,客户端就可以采取相应的行动了。
gRPC 健康检查协议基于 gRPC 定义了 API。gRPC 服务作为健康检查机制,适用于普通客户端–服务器端场景以及其他的控制系统(如负载均衡)。代码清单 8-6 展示了 gRPC 健康检查 API 的标准服务定义。
代码清单 8-6 健康检查 API 的 gRPC 服务定义
syntax = "proto3";
package grpc.health.v1;
message HealthCheckRequest { ➊
string service = 1;
}
message HealthCheckResponse { ➋
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse); ➌
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse); ➍
}
- ❶ 健康检查请求的消息结构。
- ❷ 带有服务状态的健康检查响应。
- ❸ 客户端可以通过调用 Check 方法查询服务器的健康状态。
- ❹ 客户端可以通过调用 Watch 方法执行流式健康检查。
健康检查服务的实现与常规的 gRPC 服务非常类似。通常会使用多路复用(第 5 章讨论过),将健康检查服务和相关的 gRPC 业务服务放到同一个 gRPC 服务器实例中。因为它是一个 gRPC 服务,所以进行健康检查与执行正常的 RPC 是一样的。它还提供了一个细粒度的服务健康语义,其中包含了每个服务健康状态的详情。同时,它还能够重用服务器上所有的已有信息,并对其进行全面控制。
基于代码清单 8-6 所示的服务接口,客户端可以调用 Check 方法(带有一个可选参数的服务名称)来检查特定服务或服务器的健康状态。
此外,客户端还可以调用 Watch 方法来执行流式健康检查。这样会采用服务器流消息模式,这意味着客户端调用方法后,服务器端会发送表示当前状态的消息,并且每当状态发生变化时,都会发送后续的新消息。
在 gRPC 健康检查协议中,有几个关键的地方需要注意。
为了反映服务器端注册的每个服务的状态,应该手动注册所有服务及其在服务器端的状态。还需要以空的服务名来设置服务器的整体状态。
客户端的每个健康检查请求都应该设置一个截止时间,如果 RPC没有在截止时间内完成,客户端就可以确定服务器处于非健康状态。
对于每个健康检查请求,客户端可以设置一个服务名,也可以将其留空。如果请求带有服务名,并且服务可以在服务器注册中心找到,则响应必须是 HTTP OK 状态,并且 HealthCheckResponse消息的状态字段要设置为特定服务的状态(SERVING 或NOT_SERVING)。如果在服务器注册中心中无法找到该服务,则服务器应该响应 NOT_FOUND 状态。
如果客户端需要查询服务器的整体状态,而不是特定服务的状态,那么客户端在发送请求时,可以带一个空的字符串值,这样服务器就会以整体健康状态作为响应。
如果服务器端没有健康检查 API,那么客户端需要自行处理。
健康检查服务是被其他 gRPC 消费者或中间子系统(如负载均衡器或代理)所使用的。相对于从头实现客户端,我们更倾向于使用现有的健康检查客户端实现,如 grpc_health_probe。