python-3.x - 使用 docker-compose 运行时无法让 Flask 应用程序与 Tensorflow Serving 通信
问题描述
我有一个非常简单的 Flask 应用程序,并且我已经训练了一个模型来对图像进行推理,所以我想要做的是能够通过 docker-compose 同时运行这两个应用程序。这是我的docker-compose.yml
文件的样子
version: "2"
services:
molo:
build:
context: ./
dockerfile: molo/Dockerfile
ports:
- 8003:8003
tensorflow-serving:
image: tensorflow/serving
ports:
- 8500:8500
- 8501:8501
volumes:
- './models:/models'
command:
- '--model_config_file=/models/models.config'
- '--model_config_file_poll_wait_seconds=60'
- '--allow_version_labels_for_unavailable_models=true'
molo
是我给 Flask 应用服务起的傻名字。这里还有 Flask 应用程序的 Dockerfile。
FROM python:3.8-slim-buster
COPY ./molo/ /molo
COPY ./requirements.txt requirements.txt
COPY ./utilities /utilities
RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install -r requirements.txt
RUN python3 -m pip install utilities/
ENV FLASK_DEBUG=False
EXPOSE 8003
RUN ["chmod", "+x", "/molo/entrypoint.sh"]
ENTRYPOINT ["/molo/entrypoint.sh"]
事情就是这样。当我运行docker-compose up --build
这两个服务时,没有问题。我可以访问烧瓶应用程序,并且可以通过 gRPC 通过 python 控制台将请求发送到 TensorFlow 服务服务。但是,当我尝试访问 Flask 应用程序中的端点时,该端点应该与我在控制台中执行的操作完全相同,我得到了一堆InactiveRPC
错误,我不知道为什么它不起作用。我的猜测是我可能指定了错误的地址,但这只是一个猜测。
以下是 Flask 应用程序的内容(目前只是一个文件)。
import os
import grpc
import simplejson as json
from dotenv import load_dotenv
from flask import Flask
from tensorflow_serving.apis import predict_pb2, get_model_metadata_pb2, prediction_service_pb2_grpc
from tensorflow_serving.apis.model_pb2 import ModelSpec
from google.protobuf.json_format import MessageToJson
from utilities.route_decorators import status_code_decorator
load_dotenv()
app = Flask(__name__)
MODEL_URI = "0.0.0.0:8500"
@app.route("/", methods=['GET'])
@status_code_decorator
def home():
return "Welcome to Molo!"
@app.route("/molo/info/<model_name>", defaults={"model_name": "dense_net"}, methods=["GET"])
@status_code_decorator
def molo_info(
model_name: str
):
channel = grpc.insecure_channel(MODEL_URI)
stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
model_spec = ModelSpec(name=model_name, signature_name="serving_default")
request = get_model_metadata_pb2.GetModelMetadataRequest(model_spec=model_spec)
request.metadata_field.append("signature_def")
result = stub.GetModelMetadata(request, 5.0)
metadata = json.loads(MessageToJson(result))
return metadata
@app.route("/molo/predict", methods=["GET"])
@status_code_decorator
def molo_predict():
return {"prediction": "some label"}
if __name__ == "__main__":
app.run(
host=os.environ.get("FLASK_HOST", "0.0.0.0"),
port=os.environ.get("FLASK_PORT", 8003),
debug=os.environ.get("FLASK_DEBUG", True)
)
如果有人经历过类似的事情或者可能知道我做错了什么,我将非常感激,因为我花了一整天的时间可能只是想弄清楚这一点。
编辑
这是我遇到的示例错误。
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
molo_1 | status = StatusCode.UNAVAILABLE
molo_1 | details = "failed to connect to all addresses"
molo_1 | debug_error_string = "{"created":"@1621306525.139840351","description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":4133,"referenced_errors":[{"created":"@1621306525.139835546","description":"failed to connect to all addresses","file":"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc","file_line":397,"grpc_status":14}]}"
解决方案
推荐阅读
- python - 在没有 sql 函数的情况下在 PySpark 中对数据框进行排序
- javascript - 引导按钮切换/切换状态
- excel - 如何在 GSHEETS(或 EXCEL)中格式化 20 位数字
- jenkins - Jenkins Amazon EC2 插件 WinRM 无限循环
- python - 为什么 AbstractSet 不包含并集和交集?
- visual-studio-2019 - 如何在 VS 2019 中调试意外的 MSTest 交互
- javascript - 在 Vue 组件中动态包装文本
- apache-spark - 如何在执行 map 之前获取特定分区的所有输入?
- python - 从作为参数给出的类继承
- javascript - eventstream zip 和 Bacon.when 有什么区别