flask使用WSGI部署以及压力测试
本文中涉及到的代码都在github上做了托管,github地址为:https://github.com/jiaxiaolei/my_flask_project
应用举例:
$ tree
.
├── flask_twisted.py
├── gevent_server.py
├── hello.py
├── README.md
├── start_gunicore.sh
├── start.sh
├── templates
│ └── hello.html
├── test
│ └── test_siege.sh
├── tornado_server.py
filename: hello.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
@app.route('/<name>')
def index(name=None):
return render_template('hello.html', name=name)
if __name__ == '__main__':
app.run(host='0.0.0.0',port=13579, debug=False)
filename: start.sh
python hello.py
filename: templates/hello.html
from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
启动flask web server:
$ ./start.sh
127.0.0.1 - - [15/Aug/2017 22:06:54] "GET /3344 HTTP/1.1" 200 -
127.0.0.1 - - [15/Aug/2017 22:06:54] "GET /3344 HTTP/1.1" 200 -
127.0.0.1 - - [15/Aug/2017 22:06:54] "GET /3344 HTTP/1.1" 200 -
...
进行测试:
$ siege -c 1000 -r 100 -b http://127.0.0.1:13579/3344
HTTP/1.0 200 0.02 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.01 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.00 secs: 49 bytes ==> GET /3344
[error] socket: -2136484096 connection timed out.: Connection timed out
[error] socket: 849221376 connection timed out.: Connection timed out
[error] socket: 1327605504 connection timed out.: Connection timed out
[error] socket: -2010593536 connection timed out.: Connection timed out
[error] socket: 1344390912 connection timed out.: Connection timed out
[error] socket: 1596172032 connection timed out.: Connection timed out
HTTP/1.0 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.01 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.01 secs: 49 bytes ==> GET /3344
HTTP/1.0 200 0.01 secs: 49 bytes ==> GET /3344
Transactions: 25361 hits
Availability: 99.45 %
Elapsed time: 261.27 secs
Data transferred: 1.19 MB
Response time: 1.30 secs
Transaction rate: 97.07 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 126.50
Successful transactions: 25361
Failed transactions: 139
Longest transaction: 168.89
Shortest transaction: 0.03
NOTE: -2010593536 这些数字具体什么含义,没太明白。
再次测试一组:
Transactions: 25377 hits
Availability: 99.52 %
Elapsed time: 231.44 secs
Data transferred: 1.19 MB
Response time: 1.08 secs
Transaction rate: 109.65 trans/sec
Throughput: 0.01 MB/sec
Concurrency: 118.42
Successful transactions: 25377
Failed transactions: 123
Longest transaction: 114.46
Shortest transaction: 0.03
$ gunicorn -w 1 -b 127.0.0.1:13578 hello:app
[2017-08-16 12:33:04 +0000] [4088] [INFO] Starting gunicorn 19.7.1
[2017-08-16 12:33:04 +0000] [4088] [INFO] Listening at: http://127.0.0.1:13578 (4088)
[2017-08-16 12:33:04 +0000] [4088] [INFO] Using worker: sync
[2017-08-16 12:33:04 +0000] [4092] [INFO] Booting worker with pid: 4092
[2017-08-16 12:36:51 +0000] [4088] [CRITICAL] WORKER TIMEOUT (pid:4092)
[2017-08-16 12:36:51 +0000] [4092] [INFO] Worker exiting (pid: 4092)
[2017-08-16 12:36:51 +0000] [4812] [INFO] Booting worker with pid: 4812
NOTE: 在client 发起请求访问 server 端的时候, 屏幕没有日志输出。 这和之前遇到的 gunicore 会忽视原有flask 框架的操作日志一致。
$ siege -c 1000 -r 100 -b http://127.0.0.1:13578/3344
...
HTTP/1.1 200 0.01 secs: 49 bytes ==> GET /3344
[error] socket: 631695104 connection timed out.: Connection timed out
[error] socket: 35813120 connection timed out.: Connection timed out
[error] socket: 1378645760 connection timed out.: Connection timed out
HTTP/1.1 200 0.02 secs: 49 bytes ==> GET /3344
HTTP/1.1 200 0.02 secs: 49 bytes ==> GET /3344
...
HTTP/1.1 200 0.01 secs: 49 bytes ==> GET /3344
HTTP/1.1 200 0.02 secs: 49 bytes ==> GET /3344
[error] socket: -459356416 connection timed out.: Connection timed out
[error] socket: 1328289536 connection timed out.: Connection timed out
...
Transactions: 25464 hits
Availability: 99.86 %
Elapsed time: 135.97 secs
Data transferred: 1.19 MB
Response time: 0.79 secs
Transaction rate: 187.28 trans/sec
Throughput: 0.01 MB/sec
Concurrency: 147.11
Successful transactions: 25464
Failed transactions: 36
Longest transaction: 120.95
Shortest transaction: 0.00
tornado
$ python tornado_server.py
[W 170816 12:49:26 server:27] [UOP] App is running on: localhost:5000
...
[I 170816 12:46:45 wsgi:355] 200 GET /3344 (127.0.0.1) 0.88ms
[I 170816 12:46:45 wsgi:355] 200 GET /3344 (127.0.0.1) 0.80ms
[I 170816 12:46:45 wsgi:355] 200 GET /3344 (127.0.0.1) 0.90ms
[I 170816 12:46:45 wsgi:355] 200 GET /3344 (127.0.0.1) 0.79ms
[I 170816 12:46:45 wsgi:355] 200 GET /3344 (127.0.0.1) 0.78ms
...
$ siege -c 1000 -r 100 -b http://127.0.0.1:5000/3344
...
HTTP/1.1 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.1 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.1 200 0.01 secs: 49 bytes ==> GET /3344
HTTP/1.1 200 0.01 secs: 49 bytes ==> GET /3344
...
Transactions: 25500 hits
Availability: 100.00 %
Elapsed time: 52.93 secs
Data transferred: 1.19 MB
Response time: 0.38 secs
Transaction rate: 481.77 trans/sec
Throughput: 0.02 MB/sec
Concurrency: 181.93
Successful transactions: 25500
Failed transactions: 0
Longest transaction: 52.31
Shortest transaction: 0.03
gevent:
$ python gevent_server.py
...
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000486
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000481
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000474
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000457
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.001040
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000845
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000814
::ffff:127.0.0.1 - - [2017-08-16 13:01:51] "GET /3344 HTTP/1.1" 200 165 0.000938
...
gevent 的日志(屏幕输出的内容)也不是太好。
$ siege -c 1000 -r 100 -b http://127.0.0.1:5000/3344
HTTP/1.1 200 0.00 secs: 49 bytes ==> GET /3344
HTTP/1.1 200 0.00 secs: 49 bytes ==> GET /3344
Transactions: 25500 hits
Availability: 100.00 %
Elapsed time: 25.74 secs
Data transferred: 1.19 MB
Response time: 0.23 secs
Transaction rate: 990.68 trans/sec
Throughput: 0.05 MB/sec
Concurrency: 226.40
Successful transactions: 25500
Failed transactions: 0
Longest transaction: 7.21
Shortest transaction: 0.01
twisted:
NOTE: 因为twisted 和 flask 集成没有调试通。这里使用了一个flask 插件
flask-twisted
.
$ python flask_twisted.py
# NOTE: 很不幸,屏幕没有任何信息输出。
$ siege -c 1000 -r 100 -b http://127.0.0.1:13579/3344
Transactions: 25500 hits
Availability: 100.00 %
Elapsed time: 73.40 secs
Data transferred: 1.19 MB
Response time: 0.72 secs
Transaction rate: 347.41 trans/sec
Throughput: 0.02 MB/sec
Concurrency: 250.12
Successful transactions: 25500
Failed transactions: 0
Longest transaction: 3.81
Shortest transaction: 0.02
总结
之前我在给Flask做WSGIServer 选型的时候选择了Tronado。
经过这次多种WSGI的使用比较和性能测试,验证了当时的选择是正确的。从性能和使用习惯上,都推荐选择Tornado.
扩展阅读
flask 四种wsgi方式对比(tornado,Gunicorn,Twisted,Gevent)
http://blog.csdn.net/marscrazy_90/article/details/41943211
简介:
使用了siege 做压力测试。
提供了启动脚本和测试脚本,但是具体的WSGI配合使用不详细。
我基于此做了完善。
独立 WSGI 容器
http://docs.jinkan.org/docs/flask/deploying/wsgi-standalone.html
简介:
flask 的说明文档。
Linux下四款Web服务器压力测试工具(http_load、webbench、ab、siege)介绍
http://www.cnblogs.com/shipengzhi/archive/2012/10/09/2716766.html
简介:
介绍了4种压力测试工具的使用方法,以及结果分析。