深度学习模型服务端部署——flask+gunicorn+supervisor+nginx+docker

news2024/11/15 11:16:51

前言:深度学习模型经过前期的训练调优评估,最终得到一个精度速度满足要求的模型(.pth, .ckpt,或者.onnx等等格式),但模型要实际用起来,还得部署起来,部署分为在移动端芯片上和服务器上。在移动端芯片部署通常还需要对模型进行格式转换,转换为芯片指定格式才能在芯片上进行推理,比如瑞芯微芯片的.rknn格式,海思芯片的.wk格式,推理代码通常都是c++代码编写。而在服务器上进行部署由于可以利用强大的GPU算力,对模型加速要求不是很高,为了适当提速,通常将模型转换为TensorRT格式,利用Nvidia对算子做的加速实现减少模型推理耗时;服务器上部署也有C++代码实现和Python代码实现,但都是基于后端支撑,提供api服务供使用者调用,本文是基于服务器上部署深度学习模型,利用python代码实现,提供flask接口供使用者调用。

文章目录

  • 一、制作Docker镜像
    • 1、下载nvidia/cuda的Ubuntu镜像
    • 2、运行容器,进入容器后安装必要的工具,及运行工程必要的环境
    • 3、在宿主机上写test_api.py测试能否正常调用flask接口,并且能收到正常响应
    • 4、退出docker容器,用docker commit将容器提交成工程环境镜像
  • 二、了解web服务框架
  • 三、gunicorn启动服务
  • 四、nginx配置
  • 五、supervisor
  • 六、其他让程序故障重启的方式


在部署之前,需要对代码做功能性调试,这里不细细展开,这是前提,调试大概分为以下几个步骤,根据实际需要做调整:
1、整个算法工程用python加载正常模型能跑通,且已经改写成flask接口形式,运行能正常监听端口,用postman软件测试能正常返回结果;
2、若需要对模型进行加密,需要先将模型进行加密并删除原来未加密的.pt模型;代码中在加载模型部分需加入对模型进行解密的代码,这就做完了对模型进行加解密的步骤;
3、若需要对整个工程启动加入license验证(用于匹配物理机,防止将算法拷贝到其他物理机上运行),则在这一步改写代码进行license验证;
4、若需要对每个接口进行权限验证,则需改写接口函数的代码进行验证;
5、若需对整个工程代码进行加密,则放在最后一步做,保留加密后的代码;
6、运行加密后的代码,用postman软件测试能正常返回结果即可。


一、制作Docker镜像

深度学习模型部署基本都需要gpu推理,所以需要cuda环境,深度学习框架我这里选择的是pytorch;宿主机上,我的工程路径是 /mvdata/centos199/lishanlu/projects/test_project

1、下载nvidia/cuda的Ubuntu镜像

可到 https://hub.docker.com/r/nvidia/cuda 页面上直接下载,也可用docker pull命令在终端上直接拉取对应版本镜像;

docker pull nvidia/cuda:11.2.0-cudnn8-devel-ubuntu18.04(这里选的是Ubuntu18.04的cuda11.2带cudnn加速的开发环境,有完整的cuda编译文件)

2、运行容器,进入容器后安装必要的工具,及运行工程必要的环境

docker run -d --name dnn_inference -v /mvdata/centos199/lishanlu/projects/test_project:/home/work/project -p 8200:8203 nvidia/cuda:11.2.0-cudnn8-devel-ubuntu18.04 (以代码挂载的方式启动容器,并将容器的8203端口映射到宿主机的8200端口,容器名字为dnn_inference,这个命令是后台启动的容器)
注意:docker run启动可以指定gpu,但只是在docker19.0版本以后才支持 --gpus

进入容器:docker exec -it dnn_inference /bin/bash

进入容器后就可以进行调试环境了:

# 安装必备软件
apt-get update
apt-get upgrade -y -q
apt-get install vim
apt-get install net-tools
apt-get install inetutils-ping
apt-get install curl

# 安装anaconda,将宿主机上的anaconda安装文件拷贝到容器中(新开一个终端)
sudo docker cp ./Anaconda3-2022.10-Linux-x86_64.sh  dnn_inference:/home/work/(将宿主机当前目录下的anconda3安装文件复制到容器/home/work/目录下)
# 切换到容器中的终端,进行安装
cd /home/work
bash Anaconda3-2022.10-Linux-x86_64.sh   (安装同宿主机上一样,一路yes)

# 然后就可以创建虚拟环境了
conda create -n inference_env python=3.8
# 激活虚拟环境
source activate inference_env
# 安装运行my_testproject工程需要的库,深度学习模型一般需要pytorch,tensorflow,opencv,PIL,numpy,后端部署需要flask,gunicorn等等;
conda install pytorch==1.12.1 torchvision==0.13.1 torchaudio==0.12.1 cudatoolkit=11.3 -c pytorch
python -m pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
python -m pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
python -m pip install gunicorn -i https://pypi.tuna.tsinghua.edu.cn/simple
python -m pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

# 进入到挂载代码路径,运行程序,若报错缺少哪些包就继续安装
cd /home/work/project
python server.py

3、在宿主机上写test_api.py测试能否正常调用flask接口,并且能收到正常响应

url = "http://192.168.103.xxx:8200/person_detetion"
files = {'file': open('./TestDataImage/6.jpg', 'rb')}
r = requests.post(url, files=files)
#print('========== res:', r.text)
#msg = r.json()['msg']
response = r.json()['result']
#print(msg)
print(response)

4、退出docker容器,用docker commit将容器提交成工程环境镜像

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
              -a,--author="" Author
              -m,--message="" Commit message
              -p,--pause=true Pause container during commit

docker commit -a "lishanlu" -m "Deeplearning model deploy environment." -p dnn_inference dnn_deploy/inference_env:v1.0

运行docker commit命令后,通过docker images就可以看到 dnn_deploy/inference_env:v1.0这个镜像了


二、了解web服务框架

下图为web服务大致部署架构图,web应用服务采用Nginx+supervisor+(u)WSGI+flask/django部署;客户端指移动设备App,Web浏览器或者第三方应用,它们通过Nginx映射后提供的ip地址和端口实现对web应用服务的调用,这里nginx充当反向代理,负载均衡的作用,把请求分发到后面的flask/django服务,提高响应速度。uWSGI搭配Nginx实现响应速度快、内存占用率低、高可用定制、自带详尽日志等功能,支持平滑重启。Flask完全兼容WSGI (WebServer Gateway Interface )标准,便于搭建微服务框架,完全基于Unicode编码,无须处理编码问题。
在这里插入图片描述


三、gunicorn启动服务

为什么需要gunicorn启动应用?
从上图可以看出完整的web服务框架在nginx和web应用直接是存在一个uWSGI的,这里的gunicorn就属于WSGI,虽然flask自身也能提供web服务,但当请求数量增加时还是不稳定的,从下图启动flask服务弹出的警告就可以看出:
在这里插入图片描述
可以看到,flask自身应用后弹出了一条警告,提示当前处理开发模式下的服务器,不要在生产环境使用它,而是要使用一个生成环境下的WSGI服务器。WSGI(Web Server Gateway Interface)- Web服务器网关接口。是为 Python 语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。通过查看flask文档可以发现,推荐采用的WSGI就有如下几种:
在这里插入图片描述
gunicorn是基于unix系统,被广泛应用的高性能的Python WSGI HTTP Server。用来解析HTTP请求的网关服务。它通常是在进行反向代理、负载均衡(如 nginx)和一个web 应用(比如 Django 或者 Flask)之间。

在使用gunicorn启动web应用时,gunicorn 会启动一组 worker进程,所有worker进程公用一组listener,在每个worker中为每个listener建立一个wsgi server。使用命令行启动gunicorn有两种方式获取配置项,一种是在命令行配置,一种是在配置文件中获取。

命令行配置如下:

gunicorn -w 1 -b 0.0.0.0:8203 --access-logfile logs/gunicorn_access.log --error-logfile logs/gunicorn_error.log server:app -D
# -w 代表启用几个进程
# -b 代表监听端口号
# --access-logfile 指定access日志目录
# --error-logfile 指定error日志目录
# server:app 其中server是web应用服务的文件名,app代表Flask程序实例名
# -D 代表后台启动程序

启动后可通过命令 ps -ef | grep gunicorn 查看gunicorn进程信息

对于工作模式,默认是sync,即同步模式。这种模式就是说在调用的时候,必须等待调用返回结果后,决定后续的行为。而要切换成异步模型,使用gevent,此时还需要pip来安装gevent。

python -m pip install gevent -i https://pypi.tuna.tsinghua.edu.cn/simple
gunicorn -w 1 -b 0.0.0.0:8203 -k 'gevent' --access-logfile logs/gunicorn_access.log --error-logfile logs/gunicorn_error.log server:app -D

gunicorn以配置文件方式启动,通过 -c 参数指定配置文件,配置文件必须是.py格式
cat guni_conf.py查看配置文件如下:

import os
import gevent.monkey
gevent.monkey.patch_all()
import multiprocessing

bind = '0.0.0.0:8200'
workers = 1
timeout = 100
backlog = 1024
worker_class = 'gevent'
worker_connections = 1000
daemon = True
debug = False
proc_name = 'gunicorn_openmv'
pidfile = '/root/openmv/logs/gunicorn.pid'
errorlog = '/root/openmv/logs/gunicorn_error.log'
accesslog = '/root/openmv/logs/gunicorn_access.log'
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s "%(f)s" "%(a)s"'
loglevel = 'warning'
x_forwarded_for_header = 'X-FORWARDED-FOR'

gunicorn -c guni_conf.py server:app -D
至此基本的gunicorn+flask异步服务部署就实现了。


四、nginx配置

在web服务中,nginx这里充当反向代理服务器和负载均衡的作用,用nginx做反向代理和负载均衡非常简单,支持两个用法,1个proxy,1个upstream,分别用来做反向代理和负载均衡。
示例配置如下:cat nginx_conf.txt

user  root;                      #设置nginx服务的系统使用用户
worker_processes  8;             #工作进程数(和cpu核心数保持一致)

error_log  /home/lishanlu/openmv/logs/nginx_error.log info;    #nginx的错误日志
pid       /home/lishanlu/openmv/logs/nginx.pid;                #nginx服务启动时候pid



events {
    worker_connections  1024;        #每个进程允许最大连接数
}



http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    client_body_buffer_size 10M;
    client_max_body_size 100M;  

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /home/lishanlu/openmv/logs/nginx_access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    #include /etc/nginx/conf.d/*.conf;
    
    upstream city_server{
    server 192.168.103.221:8200;
    server 192.168.103.223:8200;
    }     # 负载均衡这两个服务

    server {
    listen       9602;
    server_name  localhost;

    #charset koi8-r;
 
    location / {
        proxy_pass http://city_server;
    }
    location ^~ /new/ {
    proxy_pass http://192.168.103.221:8201/;
    }
    location ^~ /ocr_ {
    proxy_pass http://192.168.103.221:5000;
    }
}
}

上述配置文件,对于city_server服务,部署在了局域网221和223两天宿主机上,nginx配置对他们做了负载均衡,nginx对外暴露的端口是9602;当nginx接收到请求时,会分析请求的接口地址形式,像类似于/person_detect这种直接转发到city_server,走负载均衡分发到两台服务的其中一台,类似于/new/face_restore这种会转发到221服务器上8201端口的应用服务,类似于/ocr_开头的请求,会转发到221服务器上5000端口的应用服务。

启动nginx服务可以通过命令nginx -c ./nginx_conf.txt
这一步做完就完全打通了web服务的链路,浏览器——>nginx——>uWSGI(采用gunicorn)——>flask应用,接下来就是要保证服务的高可用了。


五、supervisor

supervisor 是一个用 python 语言编写的进程管理工具,它可以很方便的监听、启动、停止、重启一个或多个进程。当一个进程意外被杀死,supervisor 监听到进程死后,可以很方便的让进程自动恢复,不再需要程序员或系统管理员自己编写代码来控制。

安装supervisor:

# 进入inference_env虚拟环境
source activate inference_env
pip install supervisor
# 可以看到supervisord可执行文件在anaconda3/envs/inference_env/bin目录下(同时还有supervisorctl,echo_supervisord_conf)

验证是否安装成功,执行命令:echo_supervisord_conf,会打印出supervisor的样例配置信息。(证明supervisord,supervisorctl,echo_supervisord_conf都加入了环境变量)
然后就是配置文件:

[program:gunicorn_processing]
command=/home/jovyan/anaconda3/envs/inference_env/bin/gunicorn -w 1 -b :8200 server:app
directory=/home/jovyan/project/test_project
autostart=true
autorestart=true
user=root
redirect_stderr=true

详细supervisor请参考:https://xugaoxiang.com/2019/12/04/supervisor/


六、其他让程序故障重启的方式

1、通过docker --restart=always命令启动容器

2、写一个sh文件,检测程序是否存在,若不存在则重启;将运行该sh的命令加入到crontab中

3、docker启动容器的时候就指定一个sh文件,sh文件循环查询应用服务是否存在,不存在则拉起

具体详细过程请参考:怎样使程序开机自启动和程序挂掉自动重启

我这里是采用的第3种,sh文件如下,cat run.sh

#!/bin/bash
while true
do
    exist_id=`ps -ef|grep "gunicorn"|grep -v grep|wc -l`
    if [ $exist_id -eq 0 ]
    then
        echo "gunicorn not running, now run it..."
        cd /home/work/project/test_project
        PYTHONIOENCODING=utf-8 gunicorn -c guni_conf.py service:app
    fi
    usleep 30000000
done

启动容器命令如下:sudo docker run -d --restart=always --name dnn_inference --gpus "all" --privileged -v /mvdata/centos199/lishanlu/projects/test_project:/home/work/project -p 8200:8203 dnn_deploy/inference_env:v1.0 /bin/bash /home/work/project/test_project/run.sh

综上所述,我这里采用的架构如下图所示:
在这里插入图片描述

参考:
https://xugaoxiang.com/2020/07/21/flask-12-deployment/
https://www.cnblogs.com/mokundong/p/deploy-deeplearning-model-on-flask.html
https://www.zmrenwu.com/tutorials/hellodjango-blog-tutorial/materials/74/
https://zhuanlan.zhihu.com/p/488458470

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1971425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

联邦学习开山之作论文解读与Pytorch实现FedAvg

参考文献:McMahan B, Moore E, Ramage D, et al. Communication-efficient learning of deep networks from decentralized data[C]//Artificial intelligence and statistics. PMLR, 2017: 1273-1282. 参考的文章: 1.联邦学习代码解读,超详细…

Object.defineProperty在Vue2双向绑定中的核心原理及应用

目录 1.Object.defineProperty方法 (1)介绍 (2)语法 (3)descriptor属性描述符 2.Object.defineProperty在Vue2双向绑定的核心原理 3.Object.defineProperty在vue2中的应用 (1&#xff09…

专业人士如何选?揭秘4款2024年常用的电脑录屏软件!

在这个数字化时代,无论是教学、演示、游戏直播还是软件操作,电脑录屏软件已经是我们日常工作中的好帮手。但市面上这么多的电脑录屏软件,要想挑一款既专业又好用的,还真是挺让人头疼的。今天,我们就来聊聊四款常用的电…

mybatis开启数据库的驼峰命名

在application.yml文件中添加 mybatis:configuration:map-underscore-to-camel-case: true

powerjob连接postgresql数据库(支持docker部署)

1.先去pg建一个powerjob-product库 2.首先去拉最新的包,然后找到server模块,把mysql的配置文件信息替换成pg的 spring.datasource.hikari.auto-committrue spring.datasource.remote.hibernate.properties.hibernate.dialecttech.powerjob.server.pers…

全自动迷你洗衣机什么牌子好?五款卓越内衣洗衣机大合集!

随着科技的发展,市面上也出现许多便利的小家电。其中被多次讨论起来的莫过于是内衣洗衣机,选择一款耐用、质量优秀的内衣洗衣机,不仅可以减少洗衣负担,还能提供高效的洗涤效果。然而,随着内衣洗衣机的爆火,…

maven仓库密码加密方案原理

前言 有一个要求就是说不能使用明文密码&#xff0c;需要对 settings.xml 文件中的password密码进行加密 原始配置是没有对密码进行加密的 <server><id>gleam-repo</id><username>admin</username><password>admin123</password>&l…

7.2 单变量(多->多),attention/informer

继续上文书写&#xff1a; 1 GRU Attention 收敛速度稳定的很多&#xff0c;你看这些模型是不是很容易搭&#xff0c;像积木一样&#xff1b; def create_model(input_shape, output_length,lr1e-3, warehouse"None"):input Input(shapeinput_shape)conv1 Conv…

怎么给电脑文件加密?实用的四种方法,「重磅来袭」!

小李&#xff1a;“嘿&#xff0c;小张&#xff0c;你上次提到的那个重要项目报告&#xff0c;我放在了电脑里&#xff0c;但总觉得不太安全&#xff0c;万一被误删了或者不小心泄露了怎么办&#xff1f;” 小张&#xff1a;“别担心&#xff0c;小李&#xff0c;给文件加密是…

如何提高工作效率?分享9个高效率工作的方法

如果您的企业正在面临以下问题&#xff1a; 员工敏捷性和生产力降低员工满意度不足利润下降 那么您需要创建一个运营改进指南。 这需要经常更新&#xff0c;因为这不是一次性的努力&#xff0c;而是必须定期进行的持续过程。然而&#xff0c;您的运营改进指南还必须强调优化…

java 垃圾回收器以及JVM调优方式

什么是垃圾&#xff1a; 没有被引用的对象 就是垃圾。 定位的方式 reference count: 引用计数&#xff0c;即在对象上记录着有多少个引用指向它。&#xff08;循环引用无法解决&#xff09; root searching: 根可达算法&#xff0c;根对象包含 线程栈变量&#xff0c;静态变…

bootStrap中操作行详情,删除,修改等操作

点击列表某一行的操作按钮&#xff0c;结合swtich case 出发不同操作

【2024算力大会分会 | SPIE出版】2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024)

【2024算力大会分会 | SPIE出版】 2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024) 2024 International conference on Cloud Computing, Performance Computing and Deep Learning CCPCDL往届均已完成EI检索&#xff0c;最快会后4个半月完成&#xff01; 2024中…

postgresql 11.17 开发环境rpm安装及扩展安装

进入postgresql安装文件rpm所在文件夹 cd /data460/software 执行 yum local install *.rpm 提示缺少啥依赖就对应yum安装 最后有个依赖比较特殊 Requires: llvm-toolset-7-clang > 4.0.1 You could try using --skip-broken to work around the problem 需要安装centos-re…

Spring WebFlux 整合 r2dbc 的增删改查案例

无障碍阅读方法 微信公众号关注:张家的小伙子 回复:10205文章目录 无障碍阅读方法说明准备创建mysql数据库和数据表创建一个maven项目添加项目依赖包创建项目基本目录接口启动类编写编写application配置添加跨域请求配置创建实体-数据表映射类创建Dao操作类编写自己的增删改…

VS code 美化之 代码窗背景图 日志2024/8/2

VS code 美化之 代码窗背景图 先看效果: 参考文档: VSCode设置背景图片的两种方式_vscode代码背景-CSDN博客 用插件那个方法我试了,其只会在右侧 侧边栏目出现背景图,可能是我设置不正确吧 而且安装这个插件之后出现弹窗 vscode安装出现问题什么的提示,删除这个拓展就不会有…

时间价值衰减对期权价格有哪些影响?投资必知!

今天带你了解时间价值衰减对期权价格有哪些影响&#xff1f;投资必知&#xff01;期权的时间对期权的价格和价值具有重要影响&#xff0c;这是由于期权的特性和市场机制决定的&#xff0c;其实期权的时间价值是会衰减的。 期权的时间价值&#xff0c;指的是潜在的可能性。 比…

TypeScript(switch判断)

1.switch 语法用法 switch是对某个表达式的值做出判断。然后决定程序执行哪一段代码 case语句中指定的每个值必须具有与表达式兼容的类型 语法switch(表达式){ case 值1&#xff1a; ​ 执行语句块1 break; case 值2&#xff1a; ​ 执行语句块3 break; dfault: //如…

CSDN选择:腾讯cdn缓存跟阿里云cdn对比

在如今互联网迅速发展的时代&#xff0c;内容分发网络&#xff08;CDN&#xff09;变得越来越重要。而在众多CDN提供商中&#xff0c;腾讯云和阿里云的CDN服务无疑是具代表性的两家。那么&#xff0c;这两家的CDN服务究竟有何差异&#xff1f;哪一家更值得选择呢&#xff1f;今…

Python WSGI服务器库之gunicorn使用详解

概要 在部署 Python Web 应用程序时,选择合适的 WSGI 服务器是关键的一步。Gunicorn(Green Unicorn)是一个高性能、易于使用的 Python WSGI HTTP 服务器,适用于各种应用部署场景。Gunicorn 设计简洁,支持多种工作模式,能够有效地管理和处理大量并发请求。本文将详细介绍…