为什么这个TensorFlow Serving gRPC调用会挂起?

问题描述

我们有一个相当复杂的系统,可以将不同的数据源组合在一起,为用户提供产品推荐。在这些组件中,通常是调用我们正在运行的一个或多个TensorFlow Serving模型。即使在负载很大的情况下也没问题,直到最近我们最终的某些REST API(使用Sanic框架)现在有时需要10秒钟以上才能返回。

使用cProfile,看来gRPC通道挂起了问题。但这似乎与我们最终的Web服务层中的某些事物隔离。当我分别为TensorFlow Serving组件运行以下代码时,它会轻而易举地通过一系列随机输入而没有任何问题。

这是我们正在运行的代码,其中删除了一些特定的细节:

ActivityB

这由另一个函数调用,该函数最终由如下所示的路由调用

ActivityA

在这里缺少一些基本的东西吗?当TensorFlow Serving服务没有明显的负载问题时,为什么这些请求会突然耗费这么长时间并挂起?

只需仔细检查一下,我们实际上就在FastAPI中快速重新实现了其中一种路由,虽然可能更好一些,但超时仍在发生。

更新:作为另一项测试,我们改为使用TensorFlow Serving REST HTTP API重新实现了所有功能。瞧,问题完全消失了。我觉得gRPC应该更好。仍然不知道为什么挂了。

解决方法

这里的问题不是TensorFlow Serving设置或Python代码,而是两个部分之间的网络配置方式。由Kubernetes编排TensorFlow Serving实例,然后使用Kubernetes服务将其缝合在一起。 Python代码调用的是该服务,而配置不良导致超时。

This post on the Kubernetes blog解释了详细信息。简而言之,由于gRPC依赖于HTTP / 2,因此由于复用是gRPC的优势之一,它会遇到标准Kubernetes服务的一些问题。

该解决方案(也在同一博文中)是设置一个更复杂的网络对象,以中介到TensorFlow Serving实例的连接。