flask作为一款轻量级web框架,具有诸多优点。我喜欢它的原因是它具有高度的可扩展性,广泛的各类插件,丰富的开发文档。在开发调试过程中,我们往往会简单的使用flask自带的web服务器。但是在实际的生产环境中,flask自带的web服务器很难满足需求。
所以,在生产环境中,部署flask应该用什么呢?这首先就不得不说WSGI了。
WSGI
WSGI(python web server gateway interface),python web服务器网关接口。它是python语言定义的web服务器和web应用程序之间的一种简单通用的接口。WSGI可以分为两个部分:一个是服务器或者说是网关,另一个可以成为web应用或者说是应用框架。在处理来自前端的请求是,服务器会为应用程序提供环境上下文及一个回调函数。在应用程序完成请求之后,将先前的回调函数结果返回给前端。因此,对于flask而言,这里的WSGI可以起到的功能:
- 重写环境变量,根据目标url将请求消息路由到对应的应用对象;
- 允许在一个进程中运行多个web应用程序或者框架;
- 可以起到负载均衡远端请求的作用;
- 对请求或者返回内容进行处理。
因此,只要遵照WSGI协议的web应用都可以部署在对应的webserver之后。或者说WSGI之于python,就如同Fastcgi之于php。
独立的WSGI容器
如果同时有好几个东西在面前,能够实现的功能类似,我肯定会选择更容易操作的。在flask部署这件事情上,我会选择一些独立的WSGI容器来部署flask。
gunicorn
gunicorn是一个unix用的WSGI HTTP服务器。它是从ruby的unicorn项目中移植过来的。它基于”pre-fork worker”模型,会预先开启大量进程,等待并处理接收到的请求,每个单独进程可以同时处理它们各自接到的请求,避免进程启动和销毁的开销。但是gunicorn是基于阻塞式的io,并发能力稍弱。如果要想用它来部署flask应用相当简便。
- 第一步,要通过pip安装gunicorn,
pip install gunicorn - 在安装完成之后,通过命令:
gunicorn -w 4 -b 127.0.0.1:4000 run:app就可以将所要启动的flask应用程序启动。
|
1
2
3
4
5
6
7
8
9
|
→
gunicorn
-
w
4
-
b
127.0.0.1
:
4000
run
:
app
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81837
]
[
INFO
]
Starting
gunicorn
19.6.0
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81837
]
[
INFO
]
Listening
at
:
http
:
/
/
127.0.0.1
:
4000
(
81837
)
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81837
]
[
INFO
]
Using
worker
:
sync
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81840
]
[
INFO
]
Booting
worker
with
pid
:
81840
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81841
]
[
INFO
]
Booting
worker
with
pid
:
81841
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81842
]
[
INFO
]
Booting
worker
with
pid
:
81842
[
2016
-
12
-
12
21
:
44
:
16
+
0800
]
[
81843
]
[
INFO
]
Booting
worker
with
pid
:
81843
|
其中-w指的是预定义的工作进程数,-b指的是要绑定的ip和端口,run是flask的启动python文件,app则是flask应用程序实例。比如说,我的run.py文件中是这样的
|
1
2
3
4
|
app
=
Flask
(
__name__
)
if
__name__
==
'__main__'
:
app
.
run
(
debug
=
True
,
host
=
'0.0.0.0'
,
port
=
4000
)
|
Tornado
Tornado,它是一款开源的可伸缩、非阻塞式的web服务器和工具集。在高并发的应用场景中有不错的效果。同样,要想通过Tornado来部署flask也是很简便的:
- 第一步,通过pip安装
pip install tornado - 第二部,在你的flask启动文件夹中新建py文件,然后输入这些内容,在启动的时候通过这个新建的文件启动即可
|
1
2
3
4
5
6
7
8
|
from
tornado
.
wsgi
import
WSGIContainer
from
tornado
.
httpserver
import
HTTPServer
from
tornado
.
ioloop
import
IOLoop
from
run
import
app
http_server
=
HTTPServer
(
WSGIContainer
(
app
)
)
http_server
.
listen
(
4000
)
IOLoop
.
instance
(
)
.
start
(
)
|
Gevent
Gevent是一个基于协同程序的python库,与tornado的部署方式类似,通过gevent部署flask也是十分的便利:
from gevent.wsgi import WSGIServer
from run import app
http_server = WSGIServer(('', 4000), app)
http_server.serve_forever()
nginx http代理
单纯依靠上述的这些wsgi容器在生产环境中还是不够的,往往还要在这些容器前边在部署一个nginx做http转发。nginx可以起到负载均衡、流量控制、日志管理等等更加精细的工作。对nginx的配置文件做简单的修改即可完成
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
server
{
listen
80
;
server
_name
_
;
access_log
/
var
/
log
/
nginx
/
access
.
log
;
error_log
/
var
/
log
/
nginx
/
error
.
log
;
location
/
{
proxy_pass
http
:
/
/
127.0.0.1
:
4000
/
;
proxy_redirect
off
;
proxy_set_header
Host
$
host
;
proxy_set
_header
X
-
Real
-
IP
$
remote_addr
;
proxy_set
_header
X
-
Forwarded
-
For
$
proxy_add_x_forwarded_for
;
}
}
|
其他的部署方式
当然,除了通过上述几个wsgi容器来简单的部署flask以外,还有其他几种方式也可以选择:mod_wsgi、uwsgi、fastcgi、cgi。
进程管理工具supervisor
最近在找flask生产环境部署相关的内容,无意间碰到一个神器:supervisord。
它是一个使用python编写的进程管理工具,可以很方便的开启、关闭或者重启进程。当你的主机不小心挂掉的时候,通过配制好的supervisord可以很方便的重启服务而不用一行一行敲命令。要想使用supervisord,只需要这几步:
- 第一步,当然还是安装:
sudo pip install supervisor - 安装完成之后,主要的任务就是要完成配置文件:
echo_supervisord_conf > /path/to/supervisord.conf,先将supervisord的相关配置导出到指定路径以供修改; - 下面主要修改我们比较关注的部分:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<
br
/
>
[
program
:
usercenter
]
directory
=
/
home
/
leon
/
projects
/
usercenter
;
程序的启动目录
command
=
gunicorn
-
c
gunicorn
.
py
wsgi
:
app
;
启动命令,可以看出与手动在命令行启动的命令是一样的
autostart
=
true
;
在
supervisord
启动的时候也自动启动
startsecs
=
5
;
启动
5
秒后没有异常退出,就当作已经正常启动了
autorestart
=
true
;
程序异常退出后自动重启
startretries
=
3
;
启动失败自动重试次数,默认是
3
user
=
leon
;
用哪个用户启动
redirect_stderr
=
true
;
把
stderr
重定向到
stdout,默认
false
stdout_logfile_maxbytes
=
20MB
;
stdout
日志文件大小,默认
50MB
stdout_logfile_backups
=
20
;
stdout
日志文件备份数
;
stdout
日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(
supervisord
会自动创建日志文件)
stdout_logfile
=
/
data
/
logs
/
usercenter_stdout
.
log
|
按照上边的内容,完成修改之后,比如说我的这个:
|
1
2
3
4
5
|
[
program
:
flask
]
command
=
python
.
/
app
/
main
/
run
.
py
[
program
:
getmsg
]
command
=
python
.
/
app
/
dataCollector
/
Collector
/
rocket
.
py
|
进入对应的目录,键入supervisord -c manage.conf就可以了
- 接下来通过supervisorctl就可以查看当前进程运行的状态,启动或者关闭指定进程了:
|
1
2
3
4
5
6
7
8
9
10
|
→
supervisorctl
-
c
manage
.
conf
flask
RUNNING
pid
79541
,
uptime
4
:
43
:
15
getmsg
STOPPED
Dec
12
07
:
17
PM
supervisor
>
stop
flask
flask
:
stopped
supervisor
>
status
flask
STOPPED
Dec
12
09
:
43
PM
getmsg
STOPPED
Dec
12
07
:
17
PM
|
crontab在python虚拟环境中的使用
使用python开发的同学往往会使用virtualenv来使自己的开发环境纯净不受干扰,我在使用过程中需要将一个python脚本通过crontab定期执行。在编写了对应的crontab配置文件之后,并没有按照预想的方式来。
|
1
2
|
0
,
15
,
30
,
45
*
*
*
*
python
/
home
/
eclipse
/
git
/
env
/
DouyuFan
/
app
/
dataCollector
/
Collector
/
allRooms
.
py
|
感觉明明没有问题,可脚本为什么不执行呢,思考一下,由于是在虚拟环境中运行,直接通过python+脚本文件的方式,使用的python解译器是系统中的python而不是虚拟环境中的那个。所以上边的crontab配置改成这样就可以顺利运行了:
|
1
2
|
0
,
15
,
30
,
45
*
*
*
*
/
home
/
eclipse
/
git
/
env
/
bin
/
python
/
home
/
eclipse
/
git
/
env
/
DouyuFan
/
app
/
dataCollector
/
Collector
/
allRooms
.
py
|
关于python学习相关的想法
由于自己缺乏在实际生产环境中的工作经验,这方面知识有很大一部分欠缺。只能通过自己慢慢摸索。另外,看了前几天刚买的python cookbook之后,感觉像是进入了python的新世界,有很多方法和内容都是之前没有尝试过的,未来要走的路还有很长,加油!
Flask生产部署

910

被折叠的 条评论
为什么被折叠?



