第一次在服务器上面部署Flask应用程序,踩了挺多坑,还好最终成功部署,记录一下。
uWSGI和Nginx
什么是Web服务器、Web框架、WSGI协议
- Web服务器:用于接受客户端请求,建立连接,转发响应的程序。
- Web框架:处理业务逻辑。如模板渲染、数据库查询
- WSGI协议:一种
Server
与Application
解耦的规范,只要满足协议,那么就可以选择任意Server
和Application
组合成Web
应用WSGI Server
:负责从客户端接收请求,将Request
转发给Application
,将Application
返回的Response
返回给客户端WSGI Application
:接收由Server
转发的Request
,处理并将结果返回给Server
。
而uWSGI
,则是实现了WSGI Server
协议的Web服务器,Flask
是实现了WSGI Application
协议的Web框架,也就是说它们可以直接组合成一个Web应用。
为什么还需要Nginx
- 虽然可以直接由
uWSGI
和Flask
构成网站,但是如果访问量过大,客户端请求连接就要进行长时间的等待。此时就需要Nginx
反向代理,实现分配客户端的请求连接和Web服务器的功能。
安装Python3
- 先看看现在的Python版本,默认是
Python2
$ python --version
# Python 2.7.5
- 下载
Python3
$ pwd
# /root
$ mkdir python && cd python
$ wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
- 编译安装
$ tar -zxvf Python-3.7.0.tgz # 解压
$ ls
>>> Python-3.7.0 Python-3.7.0.tgz
$ cd Python-3.7.0/
$ ./configure --prefix=/usr/local/python3.7
$ make && make install
- 备份
Python2
$ mv /usr/bin/python /usr/bin/python2.7.5
- 如果你的系统为
centos
,还需要修改yum
的配置,因为其使用的是Python2
$ vim /usr/bin/yum
$ vim /usr/libexec/urlgrabber-ext-down
# 将两个文件中的第1行都修改为Python2的路径后保存即可
#!/usr/bin/python2.7.5
- 软链
Python3
和pip3
$ ln -sv /usr/local/python3.7/bin/python3.7 /usr/bin/python
# $ ln -sv /usr/local/python3.7/bin/pip3.7 /usr/bin/pip3
- 验证
$ python -V
>>> Python 3.7.0
$ pip -V
>>> pip... for python 3.7.0
# 如果pip版本较旧可以更新一下
$ python -m pip install --upgrade pip
- Pip换源,适用于国内服务器
$ vim ~/.pip/pip.conf
# 修改成下面的阿里源
[global]
index-url=https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
安装虚拟环境
- 安装
VirtualEnv
$ sudo pip install virtualenv
- 报错:
WARNING: The script virtualenv is installed in '/usr/local/python3.7/bin' which is not on PATH.
- 原因:
virtualenv
未添加到PATH
中 - 可通过
/usr/local/python3.7/bin/virtualenv
调用virtualenv
- 通过以下方法将
virtualenv
添加到PATH
中
- 原因:
$ vim ~/.bashrc
# 末尾添加以下一行然后保存退出
export PATH=/usr/local/python3.7/bin:$PATH
# 使配置生效
$ source ~/.bashrc
- 进入项目目录
$ cd /www/wwwroot/flask/
- 创建虚拟环境
venv_flask
并进入
$ virtualenv venv_flask
$ source venv_flask/bin/activate
# 退出虚拟环境
# $ deactivate
- 安装项目所需依赖,注意此时是在虚拟环境中
(venv)$ pip install -r requirements.txt
# 前面如果没有换源,可以通过以下命令临时使用国内源
# (venv)$ pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
配置uWSGI
- 先安装
(venv)$ pip install uwsgi
- 配置uWSGI。先在项目根目录创建
uwsgi.ini
文件,配置如下
[uwsgi]
# uwsgi启动时所使用的地址与端口
socket = 127.0.0.1:5000
# 指向网站目录
chdir = /www/wwwroot/flask
# python 启动程序文件
wsgi-file = app.py
# python 程序内用以启动的 application 变量名
callable = app
# 处理器数
processes = 4
# 线程数
threads = 2
#状态检测地址
stats = 127.0.0.1:9191
- 运行测试一下
(venv)$ uwsgi uwsgi.ini
*** Starting uWSGI 2.0.18 (64bit) on [Tue Mar 3 20:13:35 2020] ***
..........
spawned uWSGI master process (pid: 17712)
spawned uWSGI worker 1 (pid: 17713, cores: 2)
spawned uWSGI worker 2 (pid: 17714, cores: 2)
spawned uWSGI worker 3 (pid: 17716, cores: 2)
spawned uWSGI worker 4 (pid: 17717, cores: 2)
*** Stats server enabled on 127.0.0.1:9191 fd: 15 ***
- 此时已经正常启动 uwsgi 并将 Flask 项目载入其中了,
Ctrl C
关闭程序。但这只是命令启动形式,要使其随同服务器启动并作为后台服务运行才是运营环境的实际所需要。因此接下来我们需要安装另一个工具来引导 uwsgi 。
配置Nginx
代码语言:javascript复制server
{
listen 80;
server_name xxx.xxx.xxx.xxx; # IP或域名
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
uwsgi_param UWSGI_PYHOME /www/wwwroot/flask/venv_flask/bin; # Python位置或虚拟环境
uwsgi_param UWSGI_CHDIR /www/wwwroot/flask; # 项目根目录
uwsgi_param UWSGI_SCRIPT app:app; # 启动项目的主程序
}
}
启动
- 后台运行
$ uwsgi --ini /www/wwwroot/flask/uwsgi.ini --daemonize /www/wwwroot/flask/log.out
# 查看进程是否启动成功
$ ps -ef | grep uwsgi
# 如果需要停止服务,可以Kill掉对应的进程ID
$ kill -9 进程id
其它
- 一开始部署到服务器时连接到数据库中没有表,一直报错。
### 经过排查才想起来还没建表,于是将代码改成这样然后手动运行了一下
if __name__ == '__main__':
db.create_all() # 建表
### 然后再将建表的语句删除,并再次运行
if __name__ == '__main__':
app.run()
- 网上很多方法都是使用
Supervisor
引用uWSGI
作常规启动服务,但是我对Supervisor
并不熟悉,于是就不折腾了。可以直接将后台运行语句添加到开机自启实现。 - 参考
- 做Python Web开发你要理解:WSGI & uWSGI
- 阿里云部署 Flask WSGI Nginx 详解