是否可以在单个 GRPC 服务器上运行同一服务的多个实例?

Posted

技术标签:

【中文标题】是否可以在单个 GRPC 服务器上运行同一服务的多个实例?【英文标题】:Is it possible to run multiple instances of same service on single GRPC server? 【发布时间】:2020-04-30 16:21:08 【问题描述】:

我试图查看是否可以在单个 GRPC 服务器上运行同一服务的不同实例,但看起来我无法这样做。所以我想知道我的测试是否做错了什么,或者根本不可能。

我的测试基于来自 grpc repo 的examples/python/multiplex:

服务:

class _GreeterServicer(helloworld_pb2_grpc.GreeterServicer):

    def __init__(self, greeter):
        self.greeter = greeter

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(
            message='Hello, ! This is !'.format(request.name, self.greeter))

服务器:

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    helloworld_pb2_grpc.add_GreeterServicer_to_server(_GreeterServicer("John"),
                                                      server)
    helloworld_pb2_grpc.add_GreeterServicer_to_server(_GreeterServicer("Jim"),
                                                      server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

客户:

def run():
    for _ in range(10):
        with grpc.insecure_channel('localhost:50051') as channel:
            greeter_stub = helloworld_pb2_grpc.GreeterStub(channel)
            greeter_response = greeter_stub.SayHello(
                helloworld_pb2.HelloRequest(name='you'))
            print("Greeter client received: " + greeter_response.message)

由于我要为每次迭代打开一个新频道,我希望得到一个混合了“你好,你!这是吉姆!”的输出。和“你好,你!这是约翰!”,但我得到的只是:

Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!
Greeter client received: Hello, you! This is John!

即我添加到服务器的 GreeterServicer 的第一个服务,它应该忽略第二个服务实例。

所以,我的问题是,是否有可能在单个服务器上执行类似的操作,以及是否有最佳实践来处理这样的场景:我想要两个几乎相同的服务,参数化不同(例如不同的 grpc 服务器?那将意味着两个实例之间的负载平衡)。

在我的特定场景中,要传递的参数是要在服务实现中使用的一些凭据,然后我的目标是让这两个相同的服务同时运行,以便最终用户不知道有多个实例。

【问题讨论】:

见:github.com/grpc/grpc/tree/master/examples/python/multiplex 这可能也很有趣:grpc.io/blog/grpc-load-balancing 感谢您提供的 grpc 平衡链接,如果我别无选择,只能使用多个服务器,那应该很有用。关于多路复用,这是我在关注这个问题时首先查找的内容,但据我所知,这些多路复用示例是关于在单个服务器中使用多个不同服务。 我不太清楚您的需求。使用 Python,除非您使用可以运行多个 worker 的东西,否则您只能使用单个线程,对吗? IIUC 在两个线程中多路复用相同的服务,应该让您也能够恢复“This is Jim”。 我的意思是,如果服务器运行多个工作器,我希望有多个服务没有问题。查看多路复用示例的代码,我看不到这种多线程是如何实现的(除了传递给服务器的线程池执行程序)。在这些示例中,将 GreeterService 和 RouteGuideService 添加到同一台服务器,好吧,这没有问题,再次添加多个 GreeterServices 不起作用。出于这个原因,我的问题是我是否在 grpc 服务器的工作方式中遗漏了任何东西(服务器/客户端选项),或者我是否应该自己实现。 【参考方案1】:

gRPC-Go 实现明确禁止在 grpc.Server 对象上多次注册相同的服务。 Code

我对 Python 的实现不是很熟悉,但我认为它也有类似的功能。对add_GreeterServicer_to_server 的调用是否返回状态或错误?

【讨论】:

没有抛出错误,没有返回值,但是正如你所指出的,据我现在所知,由于映射,服务可以被认为是单个 grpc 服务器中的单例在 HTTP/2 路径和服务实现之间完成。因此,在我运行的测试之后,我可以有多个服务器,每个服务器都配置有一个服务和不同的名称,或者一个服务器,在服务中,我可以在名称之间切换。

以上是关于是否可以在单个 GRPC 服务器上运行同一服务的多个实例?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone Swift gRPC 客户端从 Windows C# gRPC 服务器获取“连接被拒绝”

无法连接到在本地 Docker 容器中运行的 Go GRPC 服务器

从 android 客户端到 python 服务器的“不可用”gRPC 失败

存根的 gRPC 并发

多个服务器上的单个 SSL 证书以将推送通知发送到同一应用程序

MySQL中的多线程?