Python GRPC如何正确重用通道

2024-04-18 19:55:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个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:无法在关闭的通道上调用RPC由于通道在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)

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

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

有人能提出一种不泄漏地重复使用通道和存根的方法吗


Tags: toselfhostgrpcserverportaddressresponse
1条回答
网友
1楼 · 发布于 2024-04-18 19:55:10

有两种方法可以解决这个问题,它们不一定相互排斥。第一种方法是将通道的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)

人们曾经试图使用^ {CD3>}来自动调用过去的这种清理方法,但是我们发现CPython提供的关于何时和如果该方法被调用的保证太弱,不能提供类似于C++ +RAII的任何东西,所以我们只剩下像上面概述的手动选项。p>

相关问题 更多 >