【问题标题】:Python GRPC How to reuse channel correctlyPython GRPC 如何正确重用通道
【发布时间】:2021-03-11 03:30:12
【问题描述】:

我正在编写一个 GRPC python 客户端来与 GRPC 服务器进行通信,如下所示。

class GrpcClient:
    """
    Class to send request to Grpc server.
    """

    def __init__(self, host: str, port: int):
        self._server_address = host + ':' + str(port)
        with grpc.insecure_channel(self._server_address) as channel:
            self._stub = MyServerStub(channel)

    def invoke_method(self, request):
        response = self._stub.process(request)
        logging.info("response received: " + str(response))

这会导致错误 ValueError: Cannot invoke RPC on closed channel! 因为该通道在 int 上已关闭,我修改如下

    def __init__(self, host: str, port: int):
        self._server_address = host + ':' + str(port)
        channel = grpc.insecure_channel(self._server_address)
        self._stub = MyServerStub(channel)

现在通道和存根都被重用了,但我担心通道可能没有关闭,这可能导致内存泄漏

为了防止它发生,我尝试打开通道并在每个请求上创建存根,这很昂贵。

任何人都可以提出一种在没有任何泄漏的情况下重用通道和存根的方法吗?

【问题讨论】:

    标签: python python-3.x memory-leaks grpc grpc-python


    【解决方案1】:

    有两种方法可以解决这个问题,它们不一定是相互排斥的。第一个是将频道的close 方法代理到您的类并要求您的类的用户调用它。看起来像这样:

    class GrpcClient:
      def __init_(self, ...):
        self._channel = grpc.insecure_channel(...)
        self._stub = MyServerStub(self._channel)
    
      def close(self):
        self._channel.close()
    

    为了使这个 API 更简洁,您可以提供一个类似于 grpc.Channel 所做的上下文管理器 API:

    class GrpcClient:
      ...
      def __enter__(self):
        return self
      
      def __exit_(self, ...):
        self.close()
    

    然后你可以使用你的类

    with GrpcClient(...) as client:
      for task in tasks:
        do_work(client, task)
    

    过去人们曾尝试使用__del__ 自动调用此类清理方法,但我们发现 CPython 提供的关于何时以及是否调用此方法的保证太弱,无法提供类似于 C++ RAII 的任何内容,所以我们只剩下我上面概述的手动选项。

    【讨论】:

    • 第二种解决方案并没有解决问题,它只是将问题委托给 API 的调用者,并且代价高昂,因为每次调用都会导致设置和破坏通道。
    • 问题是“如何正确重用频道”。我的答案是 gRPC Python 包中规定的通道用法。期望是只要需要,您就可以保持对通道的引用,因此您的客户端需要是多次使用的长期对象。如果这对您来说是不可接受的,那么在没有显式创建通道的情况下对存根调用提供实验性支持。看看这个例子:github.com/grpc/grpc/blob/…
    猜你喜欢
    • 2020-09-27
    • 2021-11-25
    • 1970-01-01
    • 2018-08-20
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2022-11-04
    相关资源
    最近更新 更多