部署Flask应用的若干方法

开发Flask应用时,可以使用Flask自带的测试服务器,它本身只是一个在Werkzeug的一个简单服务器。出于安全考虑,千万不要把测试服务器运行到生产环境中。本文提供gevent、tornado这两种简单的方法和强大的Nginx和uWSGI组合方法。

为了让接下来的实例能完整运行,假定有如下简单的APP应用。文件app.py

1
2
3
4
5
6
7
8
9
from flask import Flask

def create_app():
app = Flask(__name__)

@app.route('/')
def index():
return 'Hello, Flask!'
return app

supervisor工具

supervisor是一个后台程序管理工具,通过把部署命令写到目录/etc/supervisor/conf.d/下,supervisor会在后台自动运行我们编写的配置。supervisor会在后台监控如此启动的程序,如此程序挂了,它会自动让其恢复。

Gevent

最简单的部署方法就是使用Gevent。gevent库使用协程(coroutines)并行地或并发地运行程序,它内部实现了WSGI接口,使用简单且能同时处理上百个HTTP连接。

当然选择最简单的方式是有弊端的,gevent没有内建限速设置,也没有HTTPS支持,它只适合于少流量的Web应用。

1
2
3
4
5
6
from gevent.wsgi import WSGIServer
from app import create_app

app = create_app()
server = WSGIServer(('', 80), app)
server.serve_forever()

部署的时候对相关模块的以来可以通过pip freeze导出。

如实借助supervisor工具,编写如下配置文件。文件放到/etc/supervisor/conf.d/目录下。

1
2
3
4
[program:webapp]
command=python3 webapp.py
directory=/home/webapp
user=allenwind

Tornado

Tornado是另外一种一样非常简单的部署方式,它内部实现了WSGI接口。如果部署在Linux下,它内部使用epoll能支持成千上万的并发连接。Tornado本身就是高性能的服务器和Web框架,还支持WebSocket建立的到服务器的长连接。

但如果部署的平台是Windows,Tornado的性能就无法发挥了,应该Windows的I/O轮询只有select。

1
2
3
4
5
6
7
8
9
10
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from app import create_app

app = create_app()
wsgi = WSGIContainer(app)
server = HTTPServer(wsgi)
server.listen(80)
IOLoop.instance().start()

如果使用supervisor工具,编写如下配置。文件放到/etc/supervisor/conf.d/目录下。

1
2
3
4
[program:webapp]
command=python3 webapp.py
directory=/home/webapp
user=allenwind

Nginx和uWSGI

上面的两种不是方法都是使用纯Python的服务器代码,性能是有限的。如果你需要更强的性能和定制化能力,使用目前最流行的不是Python Web应用方式:使用Nginx服务器作为前端,为WSGI服务器uWSGI提供反向代理服务。反向代理终止客户端的请求,并把请求转发到Web应用上,接收到响应后再把内容返回给客户端,对于客户端看了,就像反向代理在为它提供Web服务。

1
2
3
4
user <--> Nginx <--> uWSGI
user <--> Nginx <--> uWSGI
user <--> Nginx <--> uWSGI
user <--> Nginx <--> uWSGI

使用这两种组合的优势是,把轻量但强大的Nginx作为前端服务器,同时可以使用uWSGI进行定制化。

Nginx是一个非常强大的Web服务器程序,对WSGI应用有原生的支持,配置Nginx也很简单。uWSGI是一个支持包括WSGI在内的多种不同接口的Web服务器,可以作为应用的服务器使用,可以指定进程和线程的负载数量。

使用uWSGI工具。

假定我们已经写好了web应用的代码。编写如下文件(wsgi.py)

1
2
3
from app import create_app

app = create_app("app.config.MainConfig")

然后启动命令行工具,输入:

1
2
3
4
5
$uwsgi --socket 127.0.0.1:8080 \
--wsgi-file wsgi.py \
--callable app \
--processes 4 \
--threads 8

该命令指定了监听的网络地址、进程数和每个进程的线程数,可以根据实际环境适当修改。

当然,也可以使用supervisor以文本的方式启动uwsgi工具,在项目的根目录下创建文本命令如下(uwsgi.ini):

1
2
3
4
5
6
[uwsgi]
socket = 127.0.0.1:8080
wsgi-file = wsgi.py
callable = app
processes = 4
threads = 8

接着使用supervisor启动这个服务:

1
2
3
4
[program:app]
command=uwsgi uwsgi.ini
directory=/home/allen/app
user=allen

接下来要配置Nginx服务器。Nginx的配置文件放到目录/etc/nginx/sites-available/下。新建nginx.conf配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name your_domain_name;

location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8080;
}
location /static {
alias /home/allen/app/src/static;
}
}

这个配置文件高速Nginx服务器监听80端口以接收外部请求,并把请求转发到8080的WSGI本地应用中。另外,静态文件Nginx自己独立处理,以提升性能。

Nginx和Gunicorn

如果使用Gunicorn替代uWSGI,操作上也是类似。

1
2
3
4
user <--> Nginx <--> Gunicorn
user <--> Nginx <--> Gunicorn
user <--> Nginx <--> Gunicorn
user <--> Nginx <--> Gunicorn

转载请包括本文地址:https://allenwind.github.io/blog/4833
更多文章请参考:https://allenwind.github.io/blog/archives/