python - 为什么这个 TensorFlow Serving gRPC 调用会挂起?
问题描述
我们有一个相当复杂的系统,它将不同的数据源拼接在一起,为我们的用户提供产品推荐。在这些组件中,通常调用我们正在运行的一个或多个 TensorFlow Serving 模型。这一直很好,即使在负载下,直到最近我们的一些最终 REST API(使用 Sanic 框架)现在有时需要 10 多秒才能返回。
使用cProfile,似乎是gRPC 通道挂起的问题。但它似乎与我们最终的 Web 服务层中的某些东西是孤立的。当我为 TensorFlow Serving 组件单独运行下面的代码时,它会轻而易举地通过一系列随机输入而没有任何问题。
这是我们正在运行的代码,删除了一些具体细节:
def get_tf_serving(model_uri, model_name, input_name, output_name, X):
channel = grpc.insecure_channel(model_uri, options=MESSAGE_OPTIONS)
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
request = predict_pb2.PredictRequest()
request.model_spec.name = model_name
request.model_spec.signature_name = 'serving_default'
request.inputs[input_name].CopyFrom(util.make_tensor_proto(X.astype(np.float32), shape=X.shape))
result = stub.Predict(request, 4.0)
channel.close()
# imagine more stuff here doing something with the returned data
data = result.outputs[output_name].float_val
return data
这是由另一个函数调用的,该函数最终由如下所示的路由调用:
@doc.include(True)
async def get_suggestions(request):
user_id = request.args.get('user_id', 'null')
count = int(request.args.get('count', 10))
data = # something that itself calls `get_tf_serving`
return data
我在这里缺少一些基本的东西吗?当 TensorFlow Serving 服务没有明显的负载问题时,为什么这些请求会突然花费这么长时间并挂起?
只是为了仔细检查,我们实际上在 FastAPI 中快速重新实现了其中一个路由,虽然它可能好一点,但超时仍然不断发生。
更新:作为另一项测试,我们使用 TensorFlow Serving REST HTTP API 重新实现了所有内容。瞧,问题完全消失了。不过,我觉得 gRPC 应该更好。仍然无法弄清楚为什么会挂起。
解决方案
这里的问题不是 TensorFlow Serving 设置或 Python 代码,而是两部分之间的网络配置方式。TensorFlow Serving 实例由 Kubernetes 编排,然后使用 Kubernetes 服务拼接在一起。正是 Python 代码调用的那个服务,以及导致超时的糟糕配置。
Kubernetes 博客上的这篇文章解释了详细信息。简而言之,由于 gRPC 依赖于 HTTP/2,它在标准 Kubernetes 服务中遇到了一些问题,因为多路复用是 gRPC 的优势特性之一。
同样在同一篇博文中,解决方案是设置一个更复杂的网络对象来调解与 TensorFlow Serving 实例的连接。
推荐阅读
- jenkins - 如何访问 Jenkins ${workspace}/ 中的子目录?
- java - 如何处理响应代码?
- python - Keras:迁移学习——图像缩放显着降低了模型的性能
- c# - C# Linq First() 引发异常“序列不包含元素”,而 LongCount() 给出 1
- sql - SQL Server - 查询数据库以查找两列之间的差异
- python - 提高 Fortran 矩阵指数性能(Expokit 比 Matlab、Python 慢)
- azure - Azure Maps 请求监视
- list - 如何编写序言谓词以使用 conc(连接)操作从 List 中修剪前 N 个元素
- ios - 在 UIImageView 中更快地加载大图像
- ruby-on-rails - 如果我将 ruby 版本 2.5.1 与 rails 版本 2.3.18 一起使用会发生什么?