背景
由于目前在用的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多线程情况
配置启用多线程:
1 | # manage.py |
在Flask中配置两条测试路由
1 | import time |
先用浏览器访问\sleep:

随即立刻访问\test:

可见两次访问是不同的线程处理的,不会出现堵塞的情况。
tornado + Flask多线程情况
使用tornado托管:
1 | from tornado.wsgi import WSGIContainer |
先用浏览器访问\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服务器数量(通过多端口实现):
1 | python manage.py runserver --port=8001 |
- 使用
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环境,通过官方建议的方式部署。
