python - Python GRPC 如何正确重用通道
问题描述
我正在编写一个 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)
现在通道和存根都被重用了,但我担心通道可能没有关闭,这可能会导致内存泄漏
为了防止它,我尝试打开通道并在每个请求上创建存根,这很昂贵。
任何人都可以建议一种重用通道和存根而不会泄漏的方法吗?
解决方案
有两种方法可以解决这个问题,它们不一定是相互排斥的。第一个是将通道的close
方法代理到您的类并要求您的类的用户调用它。看起来像这样:
class GrpcClient:
def __init_(self, ...):
self._channel = grpc.insecure_channel(...)
self._stub = MyServerStub(self._channel)
def close(self):
self._channel.close()
为了让这个 API 更简洁,你可以提供一个上下文管理器 API,类似于grpc.Channel
:
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 的东西,所以我们就离开了使用我上面概述的手动选项。
推荐阅读
- html - 如何使用jQuery关闭该元素的点击之外的元素?
- python - 理解这个 kivy 程序的确切错误告诉我的问题
- linux - RAD SERVER 10.4.1 “E2597(SystemPath)\ld-linux.exe: 错误: 找不到 -lz” 部署到 Linux 64
- python - 我正在尝试在 Python 中运行这个程序,但我无法执行 def
- java - 从 unix 命令行运行 jar 文件
- cuda - Cuda GPUassert:遇到非法内存访问
- node.js - CircleCI 在 fs-extra node_modules 失败
- jquery - 基础 XML(使用 Jquery 提取)
- python - raise ValueError("Input contains NaN") ValueError: Input contains NaN 在尝试构建机器学习模型时
- flutter - 从 Flutter 中打开 Google 地图并选择地点