Python Web 项目部署
记录下一般的 Python web 项目开发后如何部署到外部服务器上,供用户访问。
1 简要
本质三件事:
- 租个服务器(含公网 ip)+配置环境
电脑 + 公网IP 自己电脑 + 拉专线
- 代码放在服务器
- 程序运行起来
2 搞一台云服务器
租一个 linux 系统的云服务器,并获得一个公网 IP,例如直接购买云服务厂商提供的云服务器。
如果是购买的云服务器,默认是会有访问限制的,当配置一个新的 web 服务后,我们需要在服务器的管理页面配置相对应的安全组规则,使得服务器能接受指定端口的出入流量,以便外部访问我们的 web 服务(例如网站)。
下面是某云服务器厂商的产品安全组示例:
3 代码同步
将本地开发代码上传到服务器上,这里现在有很多的方式。
-
本地将代码传到 git 或者 gitee 上,在服务器上再从 git 或者 gitee 上拉下来代码。
PS:
.gitignore
,这个可以直接参考 git 上有人整理好的:https://github.com/github/gitignore/blob -
使用 ftp 工具将文件上传到服务器,例如使用 winscp。
4 服务器前置知识
4.1 python 之 WSGI、uWSGI、uwsgi
参考:
简单来说:
- WSGI(Web Server Gateway Interface)是一个 Python Web 应用程序与 Web 服务器之间的接口规范,它定义了应用程序和服务器之间的标准接口,使得应用程序可以在不同的 Web 服务器上运行。WSGI 协议使得不同的 Python Web 框架(例如 Flask、Django 等)能够在不同的 Web 服务器上运行,这些服务器可以是 Apache、Nginx 等。
- uwsgi:uwsgi 是一个与 uWSGI 服务器相关的协议。uwsgi 协议是一种二进制协议,它定义了 uWSGI 服务器与应用程序之间的通信协议。
- uWSGI:uWSGI 是一个 Web 服务器,它是一个用 C 语言编写的 Web 应用程序容器,支持运行 Python、Ruby、Perl 等多种编程语言。uWSGI 服务器可以作为一个独立的应用服务器,也可以与其他 Web 服务器(如 Nginx、Apache)一起使用,通过 WSGI 协议与 Python 应用程序通信。
总结:
- WSGI,是一种描述 web 服务器(如 nginx,uWSGI 等服务器)如何与 web 应用程序(如用 Django、Flask 框架写的程序)通信协议。
- uwsgi 协议是一个 uWSGI 服务器自有的协议,它用于定义传输信息的类型(type of information),每一个 uwsgi packet 前 4byte 为传输信息类型描述,用于与 nginx 等代理服务器通信,它与 WSGI 相比是两样东西。
- uWSGI 是实现了 uwsgi 和 WSGI 两种协议的 Web 服务器。
请求传递关系:
5 服务器环境配置
1)安装 gcc【可选】
主要是用于编译 python(如果已安装可忽略)
yum install gcc -y
2)安装 python3.9
这里可以通过下面方式手动安装,当然也可以直接安装 anaconda。
-
安装 python 依赖
yum install zlib zlib-devel -y yum install bzip2 bzip2-devel -y yum install ncurses ncurses-devel -y yum install readline readline-devel -y yum install openssl openssl-devel -y yum install xz lzma xz-devel -y yum install sqlite sqlite-devel -y yum install gdbm gdbm-devel -y yum install tk tk-devel -y yum install mysql-devel -y yum install python-devel -y yum install libffi-devel -y
-
下载 python 源码
# 安装 wget yum install wget -y # 下载源码包 wget https://www.python.org/ftp/python/3.9.5/Python-3.9.5.tgz
-
解压 & 编译 & 安装
# 先解压 python 源码 tar -xvf Python-3.9.5.tgz # 进入解压后的目录 cd Python-3.9.5 # 编译 ./configure make all make install
-
测试:
python --version # or python3 --version
-
python 解释器配置国内镜像源
pip3.9 config set global.index-url https://pypi.douban.com/simple/
3)安装虚拟环境
可以安装 virtualenv,也可以直接安装 miniconda 然后基于 conda 来管理虚拟环境。
安装 miniconda:
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
# 校验文件完整性
sha256sum Miniconda3-latest-Linux-x86_64.sh
# 运行安装程序,并按照提示完成安装
bash Miniconda3-latest-Linux-x86_64.sh
# 安装完成后,需要重新打开终端或运行以下命令来更新环境变量
source ~/.bashrc
# 验证 Miniconda 是否正确安装,可以运行以下命令来查看 Miniconda 版本
conda --version
当然也可以去清华镜像源先将指定版本的 miniconda 或者 anaconda 包下下来,然后本地安装。
4)安装 uWSGI
uWSGI 官方文档:https://uwsgi-docs-zh.readthedocs.io/zh-cn/latest/WSGIquickstart.html
使用 uWSGI 运行 web 程序比默认直接运行 app.py 性能好多了。
-
首先安装依赖包:
yum install python3-devel
-
进入项目虚拟环境,安装 uWSGI
pip install uwsgi
如果报错:ERROR: Could not build wheels for uwsgi, which is required to install pyproject.toml-based projects,可以直接换用 conda 安装:
conda install -c conda-forge uwsgi
参考:https://blog.csdn.net/weixin_45800258/article/details/132810710
-
配置防火墙开启端口【根据需要,我采用的华为云,只需在安全组配置就行了】
sudo firewall-cmd --permanent --add-port=8099/tcp sudo firewall-cmd --reload
-
基于 uwsgi 运行 Web 项目(以 Flask 项目为例)
先进项目目录:cd xxx
-
方式 1:命令参数
uwsgi --http :8099 --wsgi-file app.py --callable app # --http选项指定监听的IP地址和端口号,--wsgi-file选项指定你的应用程序的入口文件
自然也可以通过选项来调整 uWSGI 的配置,例如:
--processes
:指定 worker 进程的数量--threads
:指定每个 worker 进程的线程数
-
方式 2:文件参数(推荐)
参数配置参考:
首先建议在项目目录下创建一个 uwsgi 文件夹,用来存储 uwsgi 相关文件,示例:
创建配置文件
uwsgi.ini
(这个文件名可自定义),下面是模板-
极简模板:
[uwsgi] http = 0.0.0.0:8099 chdir = /root/coding/pros/python/cv_competence # flask 项目目录 wsgi-file = app.py # flask 项目要运行的项目入口程序 callable = app processes = 2 # virtualenv = /root/miniconda3/envs/py_web # 指定虚拟环境(uwsgi 会用该虚拟环境来运行项目) buffer-size=32768
-
详细模板(注意 ini 文件的注释)
[uwsgi] ; # 启动文件,也即应用入口文件 wsgi-file = app.py ; # 应用名 就是flask文件中的 app(flask 实例) callable = app ; # 在 app 加载前切换到当前目录,指定运行目录 chdir = /root/coding/pros/python/cv_competence ; # 虚拟环境路径(conda info --envs) venv = /root/miniconda3/envs/py_web ; # 启动路由 http=0.0.0.0:8099 ; # 并发设置 ; # 启用 process manager,管理 worker 进程,worker 进程都是这个 master 进程的子进程 master = True ; # 使用 max-requests 必须采用这个选项 workers = 2 ; # 一般为 CPU 核数 * 2 (processess一样效果) ; # processes = 2 # 指定开启的工作进程数量(这里是开启2个工作进程) max-requests = 5000 ; # 最大请求数 ; # 设置每个工作进程的线程数 threads = 2 ; # 线程比进程开销更小一点。如果没有使用 threads 那么 thread 直接不工作的,必须使用 enable_threads。 listen = 1024 ; # 每个进程排队的请求数量,默认为 100 太小了。并发数 = procsses * threads * listen ; # 设置用于 uwsgi 包解析的内部缓存区大小为64k。默认是4k。 buffer-size = 32768 thunder-lock = true ; # 避免惊群效应 harakiri=30 ; # 所有进程在 30s 没有响应后傻屌 ; # 监控设置 ; # stats = 127.0.0.1:9191 # 可以使用 uwsgi top 监控 python-autoreload=1 # 自动重载,开发时非常方便 ; # 指定pid文件的位置,记录主进程的pid号。 pidfile = /root/coding/pros/python/cv_competence/uwsgi/uwsgi.pid ; # 当服务器退出的时候自动删除 unix socket 文件和 pid 文件。 vacuum = true ; # 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器 daemonize = /root/coding/pros/python/cv_competence/uwsgi/uwsgi.log ; # 设置最大日志文件大小 log-maxsize = 5000000 ; 格式化日志打印 logformat-strftime=true log-date=%%Y-%%m-%%d %%H:%%M:%%S log-format=[%(ftime)] pid: %(pid) %(addr) => host: %(host)%(uri)(%(method)) in %(secs)s %(status) total-size: %(size) bytes
执行命令来启动服务:
# 激活虚拟环境 conda activate py_web # 启动服务 uwsgi --ini uwsgi/uwsgi.ini # 以后台方式运行,加个 & uwsgi --ini uwsgi/uwsgi.ini & # 重启uwsgi服务 uwsgi --reload uwsgi/uwsgi.pid # 停止uwsgi服务 uwsgi --stop uwsgi/uwsgi.pid # 或者通过 ps -ef | grep uwsgi 查看进程及 pid,然后使用 kil -9 [pid] 来杀死进程
注意事项:
- 此时
run()
函数中添加host='0.0.0.0'
,不起作用,由 uwsgi 暴露端口和 ip。
-
5)CentOS 配置程序开机自启动【可选】
好处是:系统自己重启后,服务会自动启动(类似于 windows 的开机自启)
参考:
方式 1:rc.local 文件中添加自启动命令
-
首先编辑 rc.local 文件(没有会新建一个)
vim /etc/rc.d/rc.local
-
在文件末尾 exit 之前加上你开机需要执行的命令即可(写绝对路径,添加到系统环境变量的除外)
# 例如通过 nohup 执行 flask 中的 app.py 文件 # 可以指定用哪个 env 环境来执行 nohup /root/miniconda3/envs/face_jiance/bin/python /home/python/face_jiance/app.py > /home/python/face_jiance/nohup.out 2>&1 &
类比到 uwsgi.ini 文件,就是:
/root/miniconda3/envs/py_web/bin/uwsgi --ini /root/coding/pros/python/cv_competence/uwsgi/uwsgi.ini # 注意这里由于是在开机自启时运行,并没有事先激活虚拟环境,所以运行时需指定运行环境,或者写个 sh 脚本也行
-
为 rc.local 配置可执行权限
chmod +x /etc/rc.d/rc.local
方式 2:创建自启动 systemd 配置
参考:
-
编辑 service 文件
sudo vim /etc/systemd/system/cv_competence_project.service
输入下面内容:
[Unit] Description=uWSGI instance to serve myproject After=network.target // 表示在网络服务启动之后运行服务 [Service] User=root // 执行命令的用户 WorkingDirectory=/root/coding/pros/python/cv_competence Environment="PATH=/root/miniconda3/envs/py_web/bin" ExecStart=/root/miniconda3/envs/py_web/bin/uwsgi --ini uwsgi.ini [Install] WantedBy=multi-user.target
-
启动服务并将其添加到系统自启动项中
sudo systemctl start cv_competence_project.service sudo systemctl enable cv_competence_project.service
执行完该命令后,可以使用systemctl命令来查看该服务的状态:
sudo systemctl status cv_competence_project.service
也可以在任何时候使用以下命令停止服务并从自启动项中删除:
sudo systemctl stop cv_competence_project.service sudo systemctl disable cv_competence_project.service
6)安装 nginx(用于接收所有的浏览器请求并对不同的请求进行转发/分发)【可选】
7)制作两个脚本方便重启、停止服务【可选】
见:https://www.bilibili.com/video/BV18M41127Mf?t=325.7&p=15
参考:
- 【flask项目部署】看完这个视频,妈妈再也不担心python的项目部署啦 https://www.bilibili.com/video/BV18M41127Mf/?p=2&share_source=copy_web&vd_source=3b20378b2796b6de982b657d903c9994
- 【Flask代码开发完毕,怎样使用uswgi部署一个高性能的在线服务?】 https://www.bilibili.com/video/BV1qJ41157n4/?share_source=copy_web&vd_source=3b20378b2796b6de982b657d903c9994
本文来自博客园,作者:sinatJ,转载请注明原文链接:https://www.cnblogs.com/zishu/p/18002903