gpt4 book ai didi

python - gRPC HealthCheck 报告服务,即使它被定义为 NOT_SERVING

转载 作者:行者123 更新时间:2023-12-05 03:35:55 36 4
gpt4 key购买 nike

我正在尝试创建一个包含两个服务和每个服务中的 HealthCheck 的服务器,因此我可以独立检查它们并使用反射来了解每个服务中公开的方法。我已将一项服务硬编码为 NOT_SERVING 以对其进行测试,但是由于某种原因,它无法正常工作。我将不胜感激。

我已经创建了一个简短的脚本来重现这个结果。

原型(prototype)文件定义:

syntax = "proto3";

package test;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

service Byeer {
rpc SayBye (ByeRequest) returns (ByeReply) {}
}

message ByeRequest {
string name = 1;
}

message ByeReply {
string message = 1;
}

Python 服务器:

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)

def Check(self, request, context):
return health_pb2.HealthCheckResponse(status=health_pb2.HealthCheckResponse.SERVING)

def Watch(self, request, context):
return health_pb2.HealthCheckResponse(status=health_pb2.HealthCheckResponse.UNIMPLEMENTED)


class Byeer(test_pb2_grpc.ByeerServicer):

def SayBye(self, request, context):
return test_pb2.HelloReply(message='Bye, %s!' % request.name)

def Check(self, request, context):
return health_pb2.HealthCheckResponse(status=health_pb2.HealthCheckResponse.NOT_SERVING)

def Watch(self, request, context):
return health_pb2.HealthCheckResponse(status=health_pb2.HealthCheckResponse.UNIMPLEMENTED)


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)
health_pb2_grpc.add_HealthServicer_to_server(Greeter(), server)

test_pb2_grpc.add_ByeerServicer_to_server(Byeer(), server)
health_pb2_grpc.add_HealthServicer_to_server(Byeer(), server)

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()

当我测试反射和服务器方法时,它起作用了:

grpcurl -plaintext localhost:8000 list
grpcurl -plaintext localhost:8000 list test.Byeer
grpcurl -plaintext localhost:8000 list test.Greeter
grpcurl --plaintext -d '{"name": "John Doe"}' localhost:8000 test.Greeter/SayHello
grpcurl --plaintext -d '{"name": "John Doe"}' localhost:8000 test.Byeer/SayBye

反射报告正确的方法和服务器正确的响应。

服务器上的 HealthCheck 和 Greeter 服务也可以工作:

grpcurl --plaintext -d '' localhost:8000 grpc.health.v1.Health/Check
grpcurl --plaintext -d '{"service": "test.Greeter"}' localhost:8000 grpc.health.v1.Health/Check

因此,它会按预期报告 SERVING。

但是,Byeer 服务上的 HealthCheck,以及我使用的任何其他名称,也会报告 SERVING:

grpcurl --plaintext -d '{"service": "test.Byeer"}' localhost:8000 grpc.health.v1.Health/Check
grpcurl --plaintext -d '{"service": "xxx"}' localhost:8000 grpc.health.v1.Health/Check

而且我期望 NOT_SERVING,因为 Byeer 的检查方法已被硬编码为 NOT_SERVING。

有什么想法吗?提前致谢。

最佳答案

好的,这是一个排除反射(我的懒惰)的工作示例:

from concurrent import futures
import grpc

from grpc_health.v1.health import HealthServicer
from grpc_health.v1 import health_pb2, health_pb2_grpc

import test_pb2_grpc
import test_pb2


class Greeter(test_pb2_grpc.GreeterServicer):

def __init__(self,health):
super().__init__()
self.health=health

def SayHello(self, request, context):
self.health.set(
"greeter-eater",
health_pb2.HealthCheckResponse.ServingStatus.Value("SERVING"),
)
return test_pb2.HelloReply(message='Hello, %s!' % request.name)

class Byeer(test_pb2_grpc.ByeerServicer):

def __init__(self,health):
super().__init__()
self.health=health

def SayBye(self, request, context):
self.health.set(
"byeer-flyer",
health_pb2.HealthCheckResponse.ServingStatus.Value("NOT_SERVING"),
)
return test_pb2.HelloReply(message='Bye, %s!' % request.name)

def main():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

server.add_insecure_port('[::]:50051')

# As with any other Servicer implementations, register it
health = HealthServicer()

# Provide other services with a way to update health
greeter = Greeter(health)
byeer = Byeer(health)

test_pb2_grpc.add_GreeterServicer_to_server(
greeter,
server,
)
test_pb2_grpc.add_ByeerServicer_to_server(
byeer,
server,
)
health_pb2_grpc.add_HealthServicer_to_server(
health,
server,
)

server.start()
server.wait_for_termination()


if __name__ == "__main__":
main()

没有考虑,我需要获取 health.proto 的副本和:

# Invoke Greeter/SayHello
grpcurl \
--plaintext \
-d '{"name": "Freddie"}' \
-import-path ${PWD}/protos \
-proto health.proto \
-proto test.proto \
localhost:50051 test.Greeter/SayHello
{
"message": "Hello, Freddie!"
}

# Invoke Byeer/SayBye
grpcurl \
--plaintext \
-d '{"name": "Freddie"}' \
-import-path ${PWD}/protos \
-proto health.proto \
-proto test.proto \
localhost:50051 test.Byeer/SayBye
{
"message": "Bye, Freddie!"
}

# Health/Check Greeter service aka "greeter-eater"
grpcurl \
--plaintext \
-d '{"service":"greeter-eater"}' \
-import-path ${PWD}/protos \
-proto health.proto \
-proto test.proto \
localhost:50051 grpc.health.v1.Health/Check
{
"status": "SERVING"
}

# Health/Check Byeer service aka "byeer-flyer"
grpcurl \
--plaintext \
-d '{"service":"byeer-flyer"}' \
-import-path ${PWD}/protos \
-proto health.proto \
-proto test.proto \
localhost:50051 grpc.health.v1.Health/Check
{
"status": "NOT_SERVING"
}

解释:

  1. 您只需为每个服务器注册一次HealthServicer
  2. 与任何 gRPC 服务器一样,它 (HealthServicer),当您调用其方法(例如 Check)时,您需要为其提供一些上下文。在这种情况下,是哪种服务。
  3. 服务 名称未绑定(bind)到原型(prototype)包,而是绑定(bind)到您在 set(SERVICE,health_pb2.HealthCheckResponse.ServingStatus)
  4. 因为您可以在单个服务器上注册多个不同的 gRPC 服务(GreeterByeer),所以这些服务需要能够向 HealthServicer 提供健康上下文
  5. 为了让其他 gRPC 服务更新健康检查服务,我们需要与其他服务共享一些健康检查服务的上下文;在这里,我使用的是 Servicer 本身。
  6. 其他服务可以通过使用set 并提供一些(最好)唯一标识符来更新它们的状态;这不需要匹配服务器的原型(prototype)包/服务(但这可能是一个很好的策略)。
  7. 在实践中,您不会设置静态ServingStatus.Value,但会准确反射(reflect)该服务的状态

关于python - gRPC HealthCheck 报告服务,即使它被定义为 NOT_SERVING,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69751113/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com