Python3+uWSGI+Nginx部署Flask

2021-07-29 11:04:10 浏览数 (1)

第一次在服务器上面部署Flask应用程序,踩了挺多坑,还好最终成功部署,记录一下。

uWSGI和Nginx

什么是Web服务器、Web框架、WSGI协议

  • Web服务器:用于接受客户端请求,建立连接,转发响应的程序。
  • Web框架:处理业务逻辑。如模板渲染、数据库查询
  • WSGI协议:一种ServerApplication解耦的规范,只要满足协议,那么就可以选择任意ServerApplication组合成Web应用
    • WSGI Server:负责从客户端接收请求,将Request转发给Application,将Application返回的Response返回给客户端
    • WSGI Application:接收由Server转发的Request,处理并将结果返回给Server

uWSGI,则是实现了WSGI Server协议的Web服务器,Flask是实现了WSGI Application协议的Web框架,也就是说它们可以直接组合成一个Web应用。

为什么还需要Nginx

  • 虽然可以直接由uWSGIFlask构成网站,但是如果访问量过大,客户端请求连接就要进行长时间的等待。此时就需要Nginx反向代理,实现分配客户端的请求连接和Web服务器的功能。

安装Python3

  • 先看看现在的Python版本,默认是Python2
代码语言:javascript复制
$ python --version

# Python 2.7.5
  • 下载Python3
代码语言:javascript复制
$ pwd
# /root

$ mkdir python && cd python
$ wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
  • 编译安装
代码语言:javascript复制
$ 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
代码语言:javascript复制
$ mv /usr/bin/python /usr/bin/python2.7.5
  • 如果你的系统为centos,还需要修改yum的配置,因为其使用的是Python2
代码语言:javascript复制
$ vim /usr/bin/yum
$ vim /usr/libexec/urlgrabber-ext-down

# 将两个文件中的第1行都修改为Python2的路径后保存即可
#!/usr/bin/python2.7.5
  • 软链Python3pip3
代码语言:javascript复制
$ ln -sv  /usr/local/python3.7/bin/python3.7 /usr/bin/python
# $ ln -sv  /usr/local/python3.7/bin/pip3.7 /usr/bin/pip3
  • 验证
代码语言:javascript复制
$ python -V
>>> Python 3.7.0
$ pip -V
>>> pip... for python 3.7.0
# 如果pip版本较旧可以更新一下
$ python -m pip install --upgrade pip
  • Pip换源,适用于国内服务器
代码语言:javascript复制
$ vim ~/.pip/pip.conf

# 修改成下面的阿里源
[global]
index-url=https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com

安装虚拟环境

  • 安装VirtualEnv
代码语言:javascript复制
$ 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
代码语言:javascript复制
$ vim ~/.bashrc 

# 末尾添加以下一行然后保存退出
export PATH=/usr/local/python3.7/bin:$PATH

# 使配置生效
$ source ~/.bashrc
  • 进入项目目录
代码语言:javascript复制
$ cd /www/wwwroot/flask/
  • 创建虚拟环境venv_flask并进入
代码语言:javascript复制
$ virtualenv venv_flask
$ source venv_flask/bin/activate

# 退出虚拟环境
# $ deactivate  
  • 安装项目所需依赖,注意此时是在虚拟环境中
代码语言:javascript复制
(venv)$ pip install -r requirements.txt

# 前面如果没有换源,可以通过以下命令临时使用国内源
# (venv)$ pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

配置uWSGI

  • 先安装
代码语言:javascript复制
(venv)$ pip install uwsgi
  • 配置uWSGI。先在项目根目录创建uwsgi.ini文件,配置如下
代码语言:javascript复制
[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
  • 运行测试一下
代码语言:javascript复制
(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;            # 启动项目的主程序
      }
}

启动

  • 后台运行
代码语言:javascript复制
$ uwsgi --ini /www/wwwroot/flask/uwsgi.ini --daemonize /www/wwwroot/flask/log.out

# 查看进程是否启动成功
$ ps -ef | grep uwsgi

# 如果需要停止服务,可以Kill掉对应的进程ID
$ kill -9 进程id

其它

  • 一开始部署到服务器时连接到数据库中没有表,一直报错。
代码语言:javascript复制
### 经过排查才想起来还没建表,于是将代码改成这样然后手动运行了一下
if __name__ == '__main__':
    db.create_all()  # 建表


### 然后再将建表的语句删除,并再次运行
if __name__ == '__main__':
    app.run()
  • 网上很多方法都是使用 Supervisor 引用uWSGI 作常规启动服务,但是我对Supervisor 并不熟悉,于是就不折腾了。可以直接将后台运行语句添加到开机自启实现。
  • 参考
    • 做Python Web开发你要理解:WSGI & uWSGI
    • 阿里云部署 Flask WSGI Nginx 详解

0 人点赞