gRPC HealthCheck配置为NOT_SERVING却返回SERVING问题求助
问题根因
- gRPC中同一个服务的全限定名(这里是
grpc.health.v1.Health)只能绑定一个servicer实现,你先后把Greeter、Byeer作为HealthServicer注册到服务器,后注册的会直接覆盖前一个,这就是为什么所有健康检查请求都走到Greeter的Check逻辑,永远返回SERVING。 - 你自定义的Check方法没有处理请求参数里的
service字段,不管传入的要查询的服务名是什么,都直接返回固定状态,完全没有做服务名匹配判断。 - 不需要让业务服务类自己实现HealthServicer接口,gRPC官方的
grpc_health.v1.health模块已经提供了现成的HealthServicer实现,支持独立管理多个服务的健康状态,直接调用即可,不需要自己写Check/Watch方法。
额外小提示:你原代码中Byeer的SayBye方法返回的是HelloReply类型,不符合proto定义,修复时可以顺便修正。
修复后的服务端代码
from concurrent import futures import grpc from grpc_health.v1 import health, health_pb2, health_pb2_grpc from grpc_reflection.v1alpha import reflection import test_pb2_grpc import test_pb2 class Greeter(test_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return test_pb2.HelloReply(message='Hello, %s!' % request.name) class Byeer(test_pb2_grpc.ByeerServicer): def SayBye(self, request, context): return test_pb2.ByeReply(message='Bye, %s!' % request.name) def run_server(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=None)) server.add_insecure_port('[::]:8000') # 注册业务服务 test_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) test_pb2_grpc.add_ByeerServicer_to_server(Byeer(), server) # 初始化官方Health服务实例,统一管理所有服务健康状态 health_servicer = health.HealthServicer() health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server) # 分别设置两个业务服务的健康状态 health_servicer.set("test.Greeter", health_pb2.HealthCheckResponse.SERVING) health_servicer.set("test.Byeer", health_pb2.HealthCheckResponse.NOT_SERVING) # 可选:设置全局(空服务名)的健康状态 health_servicer.set("", health_pb2.HealthCheckResponse.SERVING) # 开启反射 services = tuple(service.full_name for service in health_pb2.DESCRIPTOR.services_by_name.values()) services += tuple(service.full_name for service in test_pb2.DESCRIPTOR.services_by_name.values()) services += (reflection.SERVICE_NAME,) reflection.enable_server_reflection(services, server) server.start() server.wait_for_termination() if __name__ == "__main__": run_server()
验证效果
修改后再调用健康检查接口就能得到预期结果:
- 查询
test.Greeter返回SERVING - 查询
test.Byeer返回NOT_SERVING - 查询不存在的服务名会返回
NOT_FOUND状态码,不会再错误返回SERVING
内容的提问来源于stack exchange,提问作者Occam's razor
相关产品推荐
相关产品推荐

