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

前言:深度学习模型经过前期的训练调优评估,最终得到一个精度速度满足要求的模型(.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 commitdocker 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 multiprocessingbind = '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服务启动时候pidevents {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
doexist_id=`ps -ef|grep "gunicorn"|grep -v grep|wc -l`if [ $exist_id -eq 0 ]thenecho "gunicorn not running, now run it..."cd /home/work/project/test_projectPYTHONIOENCODING=utf-8 gunicorn -c guni_conf.py service:appfiusleep 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.rhkb.cn/news/388533.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大龄程序员转型攻略:拥抱人工智能,开启新征程

前言 随着科技的飞速发展,人工智能浪潮席卷全球,相关岗位炙手可热。在这个背景下,许多大龄程序员开始思考如何转型,以适应时代的变化。结合自身编程基础,大龄程序员可以学习机器学习、深度学习算法,投身于…

蓝桥杯 Python 研究生组-2023-省赛-工作时长

蓝桥账户中心https://www.lanqiao.cn/problems/3494/learning/ 问题描述 小蓝手里有一份 20222022 年度自己的上班打卡记录文件,文件包含若干条打卡记录,每条记录的格式均为“yyyy-MM-dd HH:mm:ssyyyy-MM-dd HH:mm:ss”,即按照年-月-日 时:…

转录组数据去批次方法整理(combat,combat-seq,removeBatchEffect)

为什么需要去除批次效应? 批次效应是指样本在不同批次处理及测量的情况下引入与生物学情况不相关的技术误差,比如不同试剂耗材,不同操作者,不同的实验时间等。 正是因为这些非生物学的因素存在就有可能会导致我们的结果偏离真实…

网络通信---UDP

前两天做了个mplayer项目,今日继续学习 网络内容十分重要!!! 1.OSI七层模型 应用层:要传输的数据信息,如文件传输,电子邮件等(最接近用户,看传输的内容类型到底是什么) …

精进日常:每日练习与明智取舍的艺术

目录 题目1.对于非运行时异常,程序中一般可不做处理,由java虚拟机自动进行处理。2.下面哪个关键字可以用于Java的构造方法上?3.以下代码执行的结果显示是多少( )?注解总结 题目 选自牛客网 1.对于非运行时…

[工具推荐]前端加解密之Burp插件Galaxy

如果觉得该文章有帮助的,麻烦师傅们可以搜索下微信公众号:良月安全。点个关注,感谢师傅们的支持。 免责声明 本号所发布的所有内容,包括但不限于信息、工具、项目以及文章,均旨在提供学习与研究之用。所有工具安全性…

前后端demo-WarehouseManagement

前端 数据库 其他 1.git下来,解决依赖问题,前端报错因为字体文件丢失,下载字体放到fonts文件夹字体.zip官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 2.后端login验证,前端需要账号格式,linqq.com 3.自己…

国产麒麟操作系统下搞单机版

去年纪委单位的一个项目,因为单位保密性质,档案必须要保密,要求采用单机版, 要求跟EXE那样,双击打开,阿公单位信息人员电脑操作水平化滞后还是相当严重啊。 去年已经给他花了时间按他们的要求实现了。 上周…

嵌入式C++、ROS 、OpenCV、SLAM 算法和路径规划算法:自主导航的移动机器人流程设计(代码示例)

在当今科技迅速发展的背景下,嵌入式自主移动机器人以其广泛的应用前景和技术挑战吸引了越来越多的研究者和开发者。本文将详细介绍一个嵌入式自主移动机器人项目,涵盖其硬件与软件系统设计、代码实现及项目总结,并提供相关参考文献。 项目概…

Day14-Servlet后端验证码的实现

图片验证码的生成采用的是Kaptcha; Kaptcha是一个高度可配置的验证码生成工具,由Google开源。它通过一系列配置文件和插件,实现了将验证码字符串自动转换成图片流,并可以与session进行关联,从而在验证过程中使用&#…

unity2D游戏开发17战斗精灵

导入 将PlayerFight32x32.png拖Player文件夹进去 设置属性 创建动画剪辑 选中前四帧,右键Create|Animation,将动画命名为player-ire-east 其他几个动画也创建好后,将其拖到Animations|Animations文件夹 选中PlayerController,再点击Animator 创建新的Blend Tree Graph,并重…

mysql逻辑架构与sql执行过程

目录 1.背景 2.mysql逻辑架构图 3.逻辑架构解读 第一层:连接层 第二层:服务层 1.Management Serveices & Utilities 2.SQL Interface:SQL接口 3.Parser:解析器 4.Optimizer:查询优化器 5.Caches 和 Buffers:查询缓存组件 第三层:存储引擎层 第四层:数据存储层 …

后端笔记(2)--JDBC

1.JDBC简介 *JDBC(Java DataBase Connectivity)就是使用java语言操作关系型数据库的一套API *JDBC本质:(可以使用同一套代码,操作不同的关系型数据库) ​ *官方定义的一套操作所有关系型数据库的规则,即接口 ​ *各…

基于java的人居环境整治管理系统(源码+lw+部署文档+讲解等)

前言 💗博主介绍:✌全网粉丝20W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻…

“八股文”面试题:是招聘程序员的金科玉律?

引言 随着互联网的发展,现代企业对程序员的需求日益增加。在招聘过程中,许多公司采用了“八股文”式的面试题目来筛选候选人。这些题目往往涵盖了算法、数据结构、系统设计等方面的基础知识。然而,对于“八股文”在实际工作中的作用&#xf…

为什么越来越多的IT青年转行网络安全?

目前,我国互联网已经从爆发增长期进入平稳发展阶段,同时每年大量计算机相关专业的毕业生涌入就业市场,导致IT行业逐渐趋于饱和状态,甚至出现裁员现象,去年很多大厂都有裁员,不少程序员再就业成了难题。 面…

网络安全相关工作必须要有证书吗?

在当今数字化时代,网络安全已成为至关重要的领域。然而,对于从事网络安全相关工作的人员来说,证书是否是必不可少的呢? 一、网络安全证书的重要性 网络安全证书在一定程度上能够证明从业者具备相关的知识和技能。例如,CISP 作为国…

昇思25天学习打卡营第XX天|RNN实现情感分类

希望代码能维持开源维护状态hhh,要是再文件整理下就更好了,现在好乱,不能好fork tutorials/application/source_zh_cn/nlp/sentiment_analysis.ipynb MindSpore/docs - Gitee.com

python:plotly 网页交互式数据可视化工具

pip install plotly plotly-5.22.0-py3-none-any.whl pip install plotly_express 包含:GDP数据、餐厅的订单流水数据、鸢尾花 Iris数据集 等等 pip show plotly Name: plotly Version: 5.22.0 Summary: An open-source, interactive data visualization librar…

使用 Elasticsearch 和 LlamaIndex 保护 RAG 中的敏感信息和 PII 信息

作者:来自 Elastic Srikanth Manvi 在这篇文章中,我们将研究在 RAG(检索增强生成)流程中使用公共 LLMs 时保护个人身份信息 (personal identifiable information - PII) 和敏感数据的方法。我们将探索使用开源库和正则表达式屏蔽 …