本文中涉及到的代碼都在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 選型的時候選擇了Tornado。
經過這次多種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種壓力測試工具的使用方法,以及結果分析。
tornado.wsgi — Interoperability with other Python frameworks and servers
https://www.tornadoweb.org/en/stable/wsgi.html
簡介:
介紹了tornado.wsgi為其他python web框架如何集成。