Linux环境Miniconda部署Python服务
0.背景
新项目需要整合Python算法,为了减少异构系统版本及依赖的影响,降低整合难度,Python算法基于Flask开发为web服务。开发完成后,需要部署到Linux服务器作为web服务运行。因为Python工程师不熟悉Linux环境,部署的任务”顺理成章“地落到了我的头上。
1.关于Miniconda
1.定义
Miniconda是一款小巧的python环境管理工具,安装包大约只有50M多点,其安装程序中包含conda软件包管理器和Python。
2.Miniconda、Conda、Anaconda
- Conda:Conda是一个开源的包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换。它主要用于Python编程语言及其相关的数据科学、机器学习等应用领域。
- Anaconda是一个用于科学计算的Python发行版,它包含了conda、Python和许多常用的科学计算、数据分析、机器学习等库。
- Miniconda是一个轻量级的Anaconda发行版,它只包含conda和Python。相比于完整的Anaconda发行版,Miniconda的体积更小,安装速度更快,适合在资源受限的环境中使用,例如在某些嵌入式系统或容器中。
2.安装Miniconda
1.下载
官方下载地址
下载Linux版本
2.安装
上传到Linux,如/opt目录下,执行脚本:
bash Miniconda3-latest-Linux-x86_64.sh
可选 手动指定安装目录,在此步骤自定义输入,: [/root/miniconda3] >>>
# 查看版本 如果自定义安装目录的话,需要配置完环境才能使用conda命令
conda --version
3.配置环境变量
#创建miniconda环境变量文件
vim /etc/profile.d/conda_env.sh
输入内容
#Miniconda
export CONDA_HOME=/opt/miniconda3
export PATH=$PATH:$CONDA_HOME/bin
加载环境变量配置文件
source /etc/profile.d/conda_env.sh
4.禁用base环境
conda config --set auto_activate_base false
5.配置镜像源
外网下载速度极慢,配置国内镜像源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda config --set show_channel_urls yes
3.搭建Python环境
1.创建Python环境
# 创建python环境 版本3.11 名称 traffic
conda create --name traffic python=3.11
# 查看环境
conda info --envs
# 删除
conda remove -n 环境名称 --all
2.部署Python环境
# 激活环境
conda activate traffic
报错:
CondaError: Run 'conda init' before 'conda activate'
提示说先 conda init
,查了资料,大家说可以
source activate
# 退出当前虚拟环境
conda deactivate
试了一下,解决了问题。
4.部署Python项目
上传python程序(app.py基于Flask开发)到某目录下,如/home/traffic
。
创建日志文件/home/traffic/logs/app.log
,用于日志查看
# 激活环境
conda activate traffic
# 守护进程方式启动项目
nohup python app.py >/home/traffic/logs/app.log 2>&1 &
根据app.log的错误信息,安装下缺少的包:
# 安装相应的包 多个空格分隔
conda install numpy flask geopy
报错:
conda install numpy flask geopy
Channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
- defaults
Platform: linux-64
Collecting package metadata (repodata.json): done
Solving environment: failed
PackagesNotFoundError: The following packages are not available from current channels:
- geopy
Current channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
- defaults
To search for alternate channels that may provide the conda package you're
looking for, navigate to
https://anaconda.org
and use the search bar at the top of the page.
解决:
conda config --add channels conda-forge
查看日志,或者查看进程ps aux | grep python
,校验发现成功,收工。
5.gunicorn安装使用
1.WSGI(Web Server Gateway Interface)
WSGI一种Python规范,它是web服务器和web应用程序之间的接口。它的作用就像是桥梁,连接在web服务器和web应用框架之间。
根据4中启动日志WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
,启动python服务使用的是默认的web服务器。默认服务器性能极差,无法支撑需求。在此,我们使用gunicorn作为服务器替代。
gunicorn是一个用于Python程序的Web服务器,相当于Java使用的tomcat。
1.安装
确保自己在工作环境中,如不存在,先激活环境。
# 激活环境
conda activate traffic
# 下载gunicorn
pip3 install gunicorn
# 如需卸载
pip3 uninstall gunicorn
2.配置日志输出
线上排查问题,需要依赖日志,日志是必须配置的
# 项目中导入原生日治包
import logging
# 日志打印示例
app.logger.info('【function_name】原始反参是:%s', param)
# main方法设置debug启动
# gunicorn启动参数 注意日志等级设置,根据实际情况调整
nohup python -m gunicorn -w 2 -b 0.0.0.0:8888 -t 120 --log-level=info app:app > /home/traffic/app.log 2>&1 &
参数说明:
-c CONFIG : CONFIG,配置文件的路径,通过配置文件启动;生产环境使用;
-b ADDRESS : ADDRESS,ip加端口,绑定运行的主机;
-w INT, --workers INT:用于处理工作进程的数量,为正整数,默认为1;
-k STRTING, --worker-class STRTING:要使用的工作模式,默认为sync异步,可以下载eventlet和gevent并指定
--threads INT:处理请求的工作线程数,使用指定数量的线程运行每个worker。为正整数,默认为1。
--worker-connections INT:最大客户端并发数量,默认情况下这个值为1000。
--backlog int:未决连接的最大数量,即等待服务的客户的数量。默认2048个,一般不修改;
-p FILE, --pid FILE:设置pid文件的文件名,如果不设置将不会创建pid文件
--access-logfile FILE : 要写入的访问日志目录
--access-logformat STRING:要写入的访问日志格式
--error-logfile FILE, --log-file FILE : 要写入错误日志的文件目录。
--log-level LEVEL : 错误日志输出等级。
--limit-request-line INT : HTTP请求头的行数的最大大小,此参数用于限制HTTP请求行的允许大小,默认情况下,这个值为4094。值是0~8190的数字。
--limit-request-fields INT : 限制HTTP请求中请求头字段的数量。此字段用于限制请求头字段的数量以防止DDOS攻击,默认情况下,这个值为100,这个值不能超过32768
--limit-request-field-size INT : 限制HTTP请求中请求头的大小,默认情况下这个值为8190字节。值是一个整数或者0,当该值为0时,表示将对请求头大小不做限制
-t INT, --timeout INT:超过这么多秒后工作将被杀掉,并重新启动。一般设定为30秒;
--daemon: 是否以守护进程启动,默认false;
--chdir: 在加载应用程序之前切换目录;
--graceful-timeout INT:默认情况下,这个值为30,在超时(从接收到重启信号开始)之后仍然活着的工作将被强行杀死;一般使用默认;
--keep-alive INT:在keep-alive连接上等待请求的秒数,默认情况下值为2。一般设定在1~5秒之间。
--reload:默认为False。此设置用于开发,每当应用程序发生更改时,都会导致工作重新启动。
--spew:打印服务器执行过的每一条语句,默认False。此选择为原子性的,即要么全部打印,要么全部不打印;
--check-config :显示现在的配置,默认值为False,即显示。
-e ENV, --env ENV: 设置环境变量;
3.特别注意
开发过程中,发现同一个接口多次调用,返回结果不一致。最初怀疑worker间内存不共享,经查阅文档,证实了我的猜测。为提升性能,开启的多个worker,每一个都是加载python程序的unix进程(单独的)。所以,如果python服务仅作为一个计算使用是没有问题的。但是,如果存在内存中数据存储的操作,极有可能出现问题。
事已至此,在去追究设计的问题已经来不及了。退而求其次,使用了单worker多线程的方式提升性能。