准备工作
  1. 拉取 tensorflow servering 的 docker 镜像:sudo docker pull tensorflow/serving,一般是已经有的
  2. 进入到一个测试目录:cd /home/q/test_dir/
  3. 然后下载官方Demo目录:git clone https://github.com/tensorflow/serving
  4. 如果无法下载,去网站 down 下来(附件),然后 deploy 上传到 linux 实体机中

部署启动

sudo docker run -t --rm -p 8501:8501 -v "/home/q/test_dir/serving-master/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu:/models/half_plus_two" -e MODEL_NAME=half_plus_two tensorflow/serving &

NebulaGraph docker部署 docker部署模型_docker

模型预测

curl -d '{"instances": [1.0, 2.0, 5.0]}' -X POST http://localhost:8501/v1/models/half_plus_two:predict

NebulaGraph docker部署 docker部署模型_docker_02

实际模型

接下来我使用自己训练的模型,部署了一个实际的例子,可参考:

模型保存

将已存在的 h5 文件,换成 SaveModel 文件(或者直接训练完保存 SaveModel 格式的文件)

from keras.models import Sequential
from keras import backend as K
import tensorflow as tf
from keras.models import load_model

model_test = load_model("../model/model_test.h5")

# export_path 后面一定要加一个版本号的目录,不然会报错 No versions of servable test found under base path
export_path = '../models_dir/00000123/'

tf.keras.models.save_model(
    model_test,
    export_path,
    overwrite=True,
    include_optimizer=True,
    save_format=None,
    signatures=None,
    options=None
)

保存后的文件结构类似这样:其中 model_dir 和 model_test.h5 的前缀一样(model_test),1 和保存的版本号一样(00000123)

NebulaGraph docker部署 docker部署模型_json_03

启动模型容器

启动模型 docker 容器:sudo docker run -t --rm -p 8501:8501 -v "/home/q/model_dir/model_test:/models/model_test" -e MODEL_NAME=model_test tensorflow/serving &

  1. 其中 -p 8501:8501 是指端口号
  2. -v 后面的是模型目录,:前的是实际硬盘目录,后的是容器的目录
  3. tensorflow/serving 是 docker 镜像

使用日志里这行的端口号进行调用: 2021-12-20 07:13:30.936441: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ...

查看模型信息

curl http://localhost:8501/v1/models/model_test

NebulaGraph docker部署 docker部署模型_tensorflow_04

使用 saved_model_cli 命令查看模型相关信息(需要在安装有 tensorflow 包的虚拟环境执行,否则会报错:-bash: saved_model_cli: command not found ):

saved_model_cli show --dir /home/q/model_dir/model_test --all

然后会打印如下日志:默认使用的是 serving_default 这个 signature_def,通过 tf-serving 使用的时候,方法名是 predict,入参是(-1, 314) 的 matrix ,出参是一个 (-1, 4)的 matrix

NebulaGraph docker部署 docker部署模型_tensorflow_05

调用

正确使用的命令是:curl -d '{"instances": [[0.508474576, 0.316053512, xxx]]}' -X POST http://localhost:8501/v1/models/model_test:predict。返回模型的结果:

NebulaGraph docker部署 docker部署模型_docker_06


其中,需要注意的是:

  1. 入参的 key 是 instances 不可以换别的
  2. 入参的 array 需要是 matrix 二维数组
  3. 需要用 POST 请求
  4. 端口号需要是 docker 容器的端口号,一般是 8501,
  5. 路径是 /v1/models/xxx (其中 xxx 表示的是上文中启动模型 docker 时对应的 MODEL_NAME)
  6. 方法名是:predict,也就是 saved_model_cli show 里的 Method name
报错解决

以下报错是因为入参 shape 不对,或者 key 不对(应该是 instances 而不是 input)

NebulaGraph docker部署 docker部署模型_json_07

以下报错是因为端口号不对:

NebulaGraph docker部署 docker部署模型_tensorflow_08


以下报错是因为:key = instances 引号未加对:

NebulaGraph docker部署 docker部署模型_tensorflow_09

以下报错是因为输入用的是 array 而不是 matrix:

NebulaGraph docker部署 docker部署模型_json_10

python 调用
import numpy as np
# dnn feature_handle 将 json 特征处理为 matrix 格式
feature_list = feature_handle_dnn(features)
feature_matrix = np.array([feature_list])
feature_matrix
 
import json
import requests
 
data = json.dumps({
    "instances": feature_matrix.tolist()
    })
 
headers = {"content-type": "application/json"}
 
json_response = requests.post(
    'http://ipipip:8501/v1/models/model_test:predict',
    data=data, headers=headers)
 
json.loads(json_response.text)

NebulaGraph docker部署 docker部署模型_json_11

部署多个模型

部署完一个模型,之后换端口号,按照同样的方法部署其他的模型时,会报错(截图里指的是部署完上文第一个模型后的第二个不同模型):

NebulaGraph docker部署 docker部署模型_tensorflow_12


正确启动的方法:sudo docker run -p 8501:8501 -v "/home/q/model_dir/multi_models:/models/multi_models" -t tensorflow/serving --model_config_file=/models/multi_models/model.config,其中

  • -v 表示 Linux 硬盘绝对路径,绑定容器的路径,
  • -t 后的是镜像名
  • –model_config_file 是 config 的路径(用的是容器路径),固定写法/models/,后面加上配置文件的路径,如果写绝对路径或者相对路径找 models.config,会报错找不到文件或者路径
  • multi_models 是个文件夹目录,里面放的是所有模型目录(相当于在上文单模型外层套一层文件夹)
  • model.config 放在 multi_models 的子目录里(也就是和多个模型文件夹同一级目录)
  • model.config 里面的路径,也需要用容器路径,而不是 Linux 路径,不然会报错
  • 如果报错 :curl: (56) Recv failure: Connection reset by peer 则加上参数: --net=host

model.config 例子:

model_config_list:{
    config:{
      name:"model1",
      base_path:"/models/multiModel/model1",
      model_platform:"tensorflow"
    },
    config:{
      name:"model2",
      base_path:"/models/multiModel/model2",
      model_platform:"tensorflow"
    },
}

multi_models 目录结构如下:

NebulaGraph docker部署 docker部署模型_json_13


启动成功的日志:

NebulaGraph docker部署 docker部署模型_tensorflow_14

其中遇到的问题:

如果按照起一个模型的方法,会报错 unknown flag: --model_config_file:

NebulaGraph docker部署 docker部署模型_json_15


model.config 路径要写对,是容器绝对路径,不然会报错(配置文件未找到):

NebulaGraph docker部署 docker部署模型_tensorflow_16


model.config 里的路径也要写容器路径,不然会报错(加载的模型未找到):

NebulaGraph docker部署 docker部署模型_tensorflow_17


模型 docker 启动后,curl 时报错:curl: (56) Recv failure: Connection reset by peer(解决办法:启动多模型 docker 容器时增加 --net=host 参数)

NebulaGraph docker部署 docker部署模型_tensorflow_18