背景
由于目前在用的 Flask 项目涉及到一部分依赖 Windows 的处理,还无法迁移到 linux 平台,那么在 windows 环境下,要怎么部署呢?
思路
根据 Flask 官网介绍,由于 Flask 内置的服务器性能不佳,推荐的主要的部署方式有如下几种:
mod_wsgi (Apache)
独立 WSGI 容器
Gunicorn
Tornado
Gevent
uWSGI
FastCGI
CGI
上述这些部署方式,仅 Tornado 是支持在 windows 情况下部署的,配合上 Nginx 可以达到比较好的效果。可已参考 Nginx 与 tornado 框架的并发评测。
但是在实际使用中发现,tornado 的稳定性虽然很高,但是在 tornado 上部署 Flask,并不会有异步的效果。实际上还是单进程阻塞运行的,即使在 Flask 中配置了 threaded = True 也无法实现多线程使用。
Flask 多线程情况
配置启用多线程:
# manage.py
from flask_script import Server
server = Server(host=”0.0.0.0″, threaded=True)
在 Flask 中配置两条测试路由
import time
@main.route(‘/test’)
def maintest():
return ‘hello world’
@main.route(‘/sleep’)
def mainsleep():
time.sleep(60)
return ‘wake up’
先用浏览器访问 \sleep:
随即立刻访问 \test:
可见两次访问是不同的线程处理的,不会出现堵塞的情况。
tornado + Flask 多线程情况
使用 tornado 托管:
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from yourapplication import app
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000)
IOLoop.instance().start()
先用浏览器访问 \sleep:
随即立刻访问 \test:
可以发现,虽然 tornado 框架是支持异步的,但是由于实际上后台的处理是同步的,从而无法实现异步的处理的效果。如果想后台的处理也异步,则需要直接使用 tornado 来开发。
那么为什么使用 tornado 来托管 flask 呢?
Tornado 是一个开源的可伸缩的、非阻塞式的 web 服务器和工具集,它驱动了 FriendFeed。因为它使用了 epoll 模型且是非阻塞的,它可以处理数以千计的并发固定连接,这意味着它对实时 web 服务是理想的。把 Flask 集成这个服务是直截了当的
根据官网描述,其实也是为了弥足 flask 自带服务器不稳定的问题。
Flask 高并发下的表现
使用 tsung 进行压测,压力 500:
Name
highest 10sec mean
lowest 10sec mean
Highest Rate
Mean Rate
Mean
Count
connect
34.30 msec
31.91 msec
506 / sec
356.60 / sec
33.19 msec
103908
page
0.42 sec
0.29 sec
505 / sec
356.32 / sec
0.39 sec
103782
request
0.42 sec
0.29 sec
505 / sec
356.32 / sec
0.39 sec
103782
session
1mn 24sec
10.64 sec
11.4 / sec
1.21 / sec
14.24 sec
362
Code
Highest Rate
Mean Rate
Total number
200
505 / sec
356.32 / sec
104792
Name
Highest Rate
Total number
error_abort
0.5 / sec
1
error_abort_max_conn_retries
11.7 / sec
362
error_connect_econnrefused
58.6 / sec
1667
可见,在 500 的并发下,效果不佳,有很多的链接拒绝。
Flask + Nginx 在高并发下的表现
使用 tsung 进行压测,压力 500:
Name
highest 10sec mean
lowest 10sec mean
Highest Rate
Mean Rate
Mean
Count
connect
0.20 sec
30.95 msec
1810.5 / sec
626.43 / sec
0.11 sec
189853
page
0.68 sec
0.17 sec
1810.1 / sec
625.72 / sec
0.40 sec
189581
request
0.68 sec
0.17 sec
1810.1 / sec
625.72 / sec
0.40 sec
189581
Code
Highest Rate
Mean Rate
Total number
200
906.4 / sec
196.08 / sec
60689
502
1443.9 / sec
430.02 / sec
129006
Name
Highest Rate
Total number
error_abort
0.5 / sec
1
情况差不多,Flask 服务器表现还算稳定,那么尝试增加后台 Flask 服务器数量(通过多端口实现):
python manage.py runserver –port=8001
python manage.py runserver –port=8002
python manage.py runserver –port=8003
python manage.py runserver –port=8004
使用 tsung 进行压测,压力 500,4 个 Flask 服务器:
Name
highest 10sec mean
lowest 10sec mean
Highest Rate
Mean Rate
Mean
Count
connect
0.18 sec
32.57 msec
3510.1 / sec
639.92 / sec
0.11 sec
195154
page
0.49 sec
85.30 msec
3512.1 / sec
639.07 / sec
0.35 sec
194856
request
0.49 sec
85.30 msec
3512.1 / sec
639.07 / sec
0.35 sec
194856
Code
Highest Rate
Mean Rate
Total number
200
3510.1 / sec
639.50 / sec
194986
Name
Highest Rate
Total number
error_abort
0.333333333333333 / sec
1
这个效果妥妥的。
使用 tsung 进行压测,压力 1000,4 个 Flask 服务器:
Name
highest 10sec mean
lowest 10sec mean
Highest Rate
Mean Rate
Mean
Count
connect
0.20 sec
32.63 msec
2983.8 / sec
492.94 / sec
98.56 msec
150793
page
0.57 sec
90.00 msec
2976.4 / sec
491.31 / sec
0.40 sec
150275
request
0.57 sec
90.00 msec
2976.4 / sec
491.31 / sec
0.40 sec
150275
Code
Highest Rate
Mean Rate
Total number
200
2981.4 / sec
488.92 / sec
149556
502
92.5 / sec
4.02 / sec
925
Name
Highest Rate
Total number
error_abort
0.333333333333333 / sec
1
开始有一些 502 的超时错误了。
使用 tsung 进行压测,压力 1000,4 个 tornado 服务器:
Name
highest 10sec mean
lowest 10sec mean
Highest Rate
Mean Rate
Mean
Count
connect
0.18 sec
86.24 msec
2052.1 / sec
693.82 / sec
0.14 sec
208786
page
0.52 sec
0.24 sec
2060.7 / sec
693.34 / sec
0.45 sec
208606
request
0.52 sec
0.24 sec
2060.7 / sec
693.34 / sec
0.45 sec
208606
Code
Highest Rate
Mean Rate
Total number
200
2056.6 / sec
693.67 / sec
208703
在并发 1000 的情况下,是否使用 tornado 托管 Flask 效果差不多。
结论
根据上述测试,直接使用 Flask 服务器的话,由于并发处理较弱,会有各种超时或者连接拒绝的错误。通过搭配 Nginx 来进行缓冲,通过增加后端服务器数来提供并发处理量。
所以最终选择了 Nginx+ 后台 4 个 Flask 服务器的方式。由于目前 Flask 项目全体用户只有几千,目前并发情况很低,该方式完全满足使用。
如果在更大型项目中,并发上万,建议还是考虑想办法迁移至 Liunx 环境,通过官方建议的方式部署。