flask+nginx+uwsgi+supervisor项目部署

使用flask搭建的租房前端展示系统在本地开发完成一部分小功能后,现在部署到阿里云服务器上去,方便别人进行访问。本文主要记录了部署的过程,遇到的问题。

系统环境说明

Linux: CentOS Linux release 7.3.1611 (Core)
flask:0.12.2
Ngxix: nginx/1.10.2
uWSGI: 2.0.15

web访问流程图


nginx接收到web请求之后,转发给uwsgi,uwsgi负责调用flask框架对请求进行处理。
uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。WSGI (Web Server Gateway Interface),定义了 web服务器和 web应用之间的接口规范,WSGI 就像一条纽带,将 nginx服务器与 flask框架连接起来。
具体可参看:如何理解Nginx、uWSGI和Flask之间的关系? - Python - 伯乐在线

步骤流程

代码上传

将代码上传到服务器的/var/www/app中

其中app.py是flask项目的入口文件,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from flask import Flask
from flask import render_template, request
from apps.backgroud.watch import watch
from apps.user.status import user
from apps.bangdan import bangdan
app = Flask(__name__)
# 注册路由
app.register_blueprint(watch)
app.register_blueprint(user)
app.register_blueprint(bangdan)
@app.route('/')
def hello_world():
return render_template("index.html", name="xuxiaping")
if __name__ == '__main__':
app.run()

Python隔离环境安装

不同的项目可能会引用各种不同的依赖包,为了避免版本与和应用之间的冲突,VirtualEnv 可以为每个Python应用创建独立的开发环境,使他们互不影响。
没有virtualenv就先安装pip install virtualenv
1、创建flask项目运行的Python环境
在_var_www目录下执行

1
virtualenv flask

2、激活virtualenv
然后进入到flask目录中,运行source venv/bin/activate
用 activate 指令后命令符前就会出现 (flask) 字样,可通过 deactivate 退出虚拟环境

uwsgi安装和配置

uwsgi是一个pip包,直接使用pip install uwsgi即可安装
安装完后,在/var/www/app下新建uwsgi.ini文件

1
2
3
4
5
6
7
8
9
[uwsgi]
socket = 127.0.0.1:8080
pythonpath = /var/www/app
module = app ;定义模块名,即app.py
callable = app ;定义回调的遍历,app
processes = 2 ;处理的进程数
threads = 2 ;每个进程处理的线程数
req-logger = file:/var/www/app/logs/reqlog ;请求记录位置
logger = file:/var/www/app/logs/errlog ;错误日志位置

Supervisor安装和监控

在虚拟的f virtualenv环境中,运行uwsgi,退出后,很容易导致uwsgi也挂了。因此需要使用进程监控工具监控uwsgi进程,一旦挂掉就立即重启。
1、安装
在全局的python环境中执行pip install supervisor

2、配置
生成默认的配置文件echo_supervisord_conf > /etc/supervisord.conf
然后添加监控想

1
2
3
4
5
6
7
8
9
[program:uwsgi]
# 启动命令入口
command=/var/www/flask/bin/uwsgi /var/www/app/uwsgi.ini
#运行命令的用户名
user=root
autostart=true #跟随Supervisor一起启动
autorestart=true # 挂掉之后自动重启
#日志地址
stdout_logfile=/var/www/app/logs/uwsgi_supervisor.log

3、启动Supervisor
运行supervisord -c /etc/supervisord.conf就启动了Supervisor服务。
可以使用supervisorctl status查看启动的项目

Nginx安装和配置

前面关于uwsgi的相关组件,监控部署好之后,下面安装nginx
在Centos中直接yum install nginx就可以直接安装好nginx服务器
编辑nginx配置文件/var/nginx/nginx.conf
添加如下配置

1
2
3
4
5
6
7
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8080;#与uwsgi.ini中的ip和端口一致
uwsgi_param UWSGI_PYHOME /var/www/flask;#运行环境
uwsgi_param UWSGI_CHDIR /var/www/app; # 项目地址
uwsgi_param UWSGI_SCRIPT app:app; # 模块
}

配置好之后,运行systemctl start nginx.service启动nginx。

环境检查

基本环境都已经配置好后,需要进行检查配置是否正确,进程是否成功启动,是否可以访问
1、检查所有nginx,uwsgi进程是否正常运行。

2、web是否可以访问:

至此,终于完成基本的部署,网站可以访问。

问题汇总

安装不是一点问题都没有遇到。主要有两个问题

防火墙的问题

在Centos中使用firewall-cmd打开了80端口后,web上仍然无法访问,需要到阿里云的安全组控制台中进行规制配置,打开80端口才行。

url not found

首页Index - 租房系统 可以访问,但是榜单-租房系统确无法访问,问题见下图

经过排查,nginx确实将请求发送给了uwsgi(_var_log_nginx_access.log)

uwsgi也接收到nginx转发的请求(_var_www_app_logs/reqlog)

但是uwsgi没有正确的解析该请求的路由。初步分析是flask项目的路由配置错误
分析app.py的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
app = Flask(__name__)
@app.route('/')
def hello_world():
return render_template("index.html", name="xuxiaping")
if __name__ == '__main__':
# 注册路由
app.register_blueprint(watch)
app.register_blueprint(user)
app.register_blueprint(bangdan)
app.run()

将注册路由的位置移到app = Flask(__name__)下面,才解决该问题。

1
2
3
4
5
6
7
8
9
10
11
12
app = Flask(__name__)
# 注册路由
app.register_blueprint(watch)
app.register_blueprint(user)
app.register_blueprint(bangdan)
@app.route('/')
def hello_world():
return render_template("index.html", name="xuxiaping")
if __name__ == '__main__':
app.run()

至于位置的差异导致的问题,暂时不知道深层的原因是什么。

部署总结

之前部署的网站项目大多数都是使用PHP写的,主要的架子是nginx+php-fpm+thinkphp,这次尝试部署了Python的flask项目。得益之前的一些部署经验,部署速度较快,对遇到的问题有方向的尝试几次后就成功解决了。网站部署一定要有耐心,遇到错误要多分析日志,分析请求在哪个环节出现了问题,然后解决问题。

参考文章

如何理解Nginx、uWSGI和Flask之间的关系? - Python - 伯乐在线
CentOS 下用 Nginx 和 uwsgi 部署 flask 项目 - EyEder的专栏 - SegmentFault