tensorflow-serving+Docker部署自用

tensorflow-serving+Docker部署自用

简介:
当我们训练完一个tensorflow(或keras)模型后,需要把它做成一个服务,让使用者通过某种方式来调用你的模型,而不是直接运行你的代码(因为你的使用者不一定懂怎样安装),这个过程需要把模型部署到服务器上。常用的做法如使用flask、Django、tornado等web框架创建一个服务器app,这个app在启动后就会一直挂在后台,然后等待用户使用客户端POST一个请求上来(例如上传了一张图片的url),app检测到有请求,就会下载这个url的图片,接着调用你的模型,得到推理结果后以json的格式把结果返回给用户。

使用docker部署模型的好处在于,避免了与繁琐的环境配置打交道。使用docker,不需要手动安装Python,更不需要安装numpy、tensorflow各种包,直接一个docker就包含了全部。docker的方式是如今部署项目的第一选择。

一、docker用法初探

1、安装
docker安装需要两个命令:
sudo apt-get install docker
sudo apt-get install docker.io

如果在更新过程中报错,将国外源换为国内源。
具体见:更换国内源

好的学习资料不必远求
docker --help
docker run --help
2、基础命令
docker ps 查看当前正在运行的实例
docker images查看现有的镜像
docker kill 实例名称或者实例ID 杀死正在运行的实例
docker pull 镜像名称 从远程docker仓库拉下来别人已经配置好的镜像

如果执行docker相关命令,出现如下错误:

”Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission denied“

解决方法1(亲测有用)
docker命令默认只能root权限使用,使用sudo获取root(管理员)权限,运行docker命令
例:查看当前正在运行的实例

sudo docker ps

解决方法2(建议使用这个)
解决方法1实在有些繁琐,docker守护进程启动的时候,会默认赋予名字为docker的用户组读写Unix socket的权限,因此只要创建docker用户组,并将当前用户加入到docker用户组中,那么当前用户就有权限访问Unix socket了,进而也就可以执行docker相关命令

sudo groupadd docker     #添加docker用户组
sudo gpasswd -a $USER docker     #将登陆用户加入到docker用户组中
newgrp docker     #更新用户组
sudo service docker restart   #重启服务
docker ps -a    #测试docker命令是否可以使用sudo正常使用

3、docker映射
docker就是一个镜像,我们需要做的就是把docker和外部世界建立联系。最紧密的联系有如下三种:

  • 网络映射:IP和端口号
  • 磁盘映射
    使用docker -v 宿主机目录:docker目录,-v表示virtual,虚拟的路径
    一律采用绝对路径,不要投机取巧使用相对路径,这样可以给自己减少许多麻烦,大智若愚正是此意。
  • 环境变量 使用docker -e one=two,three=four 这样的命令,e表示environment

二、快速运行tensorflow-serving

添加阿里云镜像库

点击进入阿里云镜像库
tensorflow-serving+Docker部署自用_第1张图片官方操作:

  1. 安装/升级Docker客户端
    推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce

  2. 配置镜像加速器
    针对Docker客户端版本大于 1.10.0 的用户

您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["你的专属加速地址"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

我的操作:

cd etc
cd docker
sudo vim daemon.json

进入vim后,按i键插入
复制下面的代码:

{
  "registry-mirrors": ["你的专属加速地址"]
}

按Esc+Shift+:,然后按wq保存

把serving的镜像拉下来

sudo docker pull tensorflow/serving

如果我需要的是1.12.0版本的tf,那么也可以拉取指定的版本:

sudo docker pull tensorflow/serving:1.12.0

如果出现以下错误:

docker: Error response from daemon: driver failed programming external connectivity on endpoint priceless_visvesvaraya (9dd9be0149fcbef7a4c7d75a118f3900f87a4441ff92732bf5d4cc232c378739): Bind for 0.0.0.0:8501 failed: port is already allocated.

解决方法:
重启docker服务后再启动容器(具体原因)

systemctl restart docker
sudo docker pull tensorflow/serving

错误解决完成!

复制一份现有的模型,当然也可以使用自己的模型,这个仓库是tensorflow serving的整个源码库,里面给出了一些demo,我们只需要demo那一部分。

git clone https://github.com/tensorflow/serving 

使用docker命令启动服务

1.使用-v参数

TESTDATA="$(pwd)/serving/tensorflow_serving/servables/tensorflow/testdata"
sudo docker run -t --rm -p 8501:8501 \
   -v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" \
   -e MODEL_NAME=half_plus_two \
   tensorflow/serving  

上面的命令把/tmp/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu路径挂载到/models/half_plus_two,这样tensorflow_serving就可以加载models下的模型了,然后开放内部8501的http接口。

docker -e设置环境变量
docker -p设置端口映射
docker -v设置磁盘映射
docker run -t 表示是否允许伪TTY
docker run --rm表示如果实例已经存在,则先remove掉该实例再重新启动新实例
建立映射时,都是形如“宿主机:docker容器”这种格式。

2.建立磁盘映射除了使用-v参数,也可以使用mount参数。(运行时有些问题,还没找到)

sudo docker run -p 8501:8501 --mount type=bind,\  source=/tmp/tfserving/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu,\
  target=/models/half_plus_two \
  -e MODEL_NAME=half_plus_two -t tensorflow/serving  

上面的命令中:
(1)-p 8501:8501是端口映射,是将容器的8501端口映射到宿主机的8501端口,后面预测的时候使用该端口;
(2)-e MODEL_NAME=testnet 设置模型名称;
(3)–mount type=bind,source=/tmp/testnet,target=/models/testnet 是将宿主机的路径/tmp/testnet挂载到容器的/models/testnet下。/tmp/testnet是存放的是上述准备工作中保存的模型文件,‘testnet’是模型名称,包含一个.pb文件和一个variables文件夹,在/tmp/testnet下新建一个以数字命名的文件夹,如100001,并将模型文件放到该文件夹中。容器内部会根据绑定的路径读取模型文件;
(4)-t tensorflow/serving 根据名称“tensorflow/serving”运行容器;

最后万事俱备,只欠东风了。

使用RESTful API 请求预测

1.命令行下使用curl请求预测
使用Predict API请求预测,格式为:
(其中模型版本MODEL_VERSION可以省略,默认使用最新版本的模型。)

POST http://host:port/v1/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]:predict

input_data为模型的输入。

curl -d '{"instances": $input_data}' -X POST http://localhost:8501/v1/models/half_plus_two:predict

发送一个http请求测试一下:

#Query the model using the predict API
curl -d '{"instances": [1.0, 2.0, 5.0]}' \
   -X POST http://localhost:8501/v1/models/half_plus_two:predict

得到的结果如下:

{ "predictions": [2.5, 3.0, 4.5] }

这就表明服务已经部署成功了。

如果机器有公网IP(如将tfsevring部署在阿里云服务器上),则可以在其他机器上通过IP地址访问进行预测,将上面的地址中的localhost改为运行容器的机器的公网IP地址即可。

2.使用Python代码请求预测

import requests
import numpy as np
SERVER_URL = 'http://localhost:8501/v1/models/half_plus_two:predict'
def prediction():
    predict_request='{"instances":%s}' % str([[[10]*7]*7])
    #print(predict_request)
    response = requests.post(SERVER_URL, data=predict_request)
    prediction = response.json()['predictions'][0]
    print(prediction)
    
if __name__ == "__main__":
    prediction()

使用gRPC 请求预测

需要安装tensorflow-serving-api,(这里省略)

三、tensorflow-serving的默认配置

我们需要了解tensorflow/serving这个镜像的默认配置,镜像的默认配置就像电路板的引脚一样,是固定的。

serving镜像提供了两种调用方式:gRPC和HTTP请求。gRPC默认端口是8500,HTTP请求的默认端口是8501,serving镜像中的程序会自动加载镜像内/models下的模型,通过MODEL_NAME指定/models下的哪个模型。

你可能感兴趣的:(tensorflow,tf-serving部署)