Gunicorn 几种 Worker class 性能测试比较
Tags gunicorn flask gevent eventlet tornado By crazygit On 2015-06-26
简介
- Gunicorn, 一个支持WSGI协议的web服务器
- Flask, 一个轻量级的python web框架
Gunicorn目前自带支持几种工作方式:
- sync (默认值)
- eventlet
- gevent
- tornado
测试环境准备
- python 2.7+
- redis-server 2.8.4
- 压力测试工具ab
-
代码及相关python包准备 创建虚一个新的虚拟环境并安装需要的包
$ mkvirtualenv test $ workon test $ cat requirements.txt gunicorn==19.3.0 flask==0.10.1 flask-redis==0.1.0 gevent==1.0.2 tornado==4.2 eventlet==0.17.4 $ pip install -r requirements.txt
测试程序
app.py
from flask import Flask from flask_redis import FlaskRedis REDIS_URL = "redis://:password-string@localhost:6379/0" app = Flask(__name__) app.config.from_object(__name__) redis = FlaskRedis(app, True) @app.route("/") def index(): redis.incr("hit", 1) return redis.get("hit") if __name__ == '__main__': app.run()
开始测试
-
使用ab工具,并行500个客户端, 发送50000次请求
$ ab -c 500 -t 30 -r "http://127.0.0.1:8000/"
-
分别使用四种方式启动使用服务, 并开启4个worker
$ gunicorn -w 4 app:app --error-logfile - --worker-class sync $ gunicorn -w 4 app:app --error-logfile - --worker-class gevent $ gunicorn -w 4 app:app --error-logfile - --worker-class tornado $ gunicorn -w 4 app:app --error-logfile - --worker-class eventlet
-
结果比较
Worker class | Time taken for tests | Complete requests | Failed requests | Requests per second | 用户平均请求等待时间 | 服务器平均处理时间 | 最小连接时间 | 平均连接时间 | 50%的连接时间 | 最大连接时间 |
sync | 37.363 s | 49928 | 793 | 1336.29 | 374.169 ms | 0.748 ms | 5 ms | 75 ms | 17 ms | 31746 ms |
tornado | 13.995 | 50000 | 543 | 3572.64 | 139.953 ms | 0.280 ms | 6 ms | 110 ms | 24 ms | 13837 ms |
eventlet | 8.156 | 50000 | 0 | 6130.74 | 81.556 | 0.163 ms | 2 ms | 80 ms | 62 ms | 3153 ms |
gevent | 7.647 s | 50000 | 0 | 6538.23 | 76.473 ms | 0.153 ms | 1 ms | 74 ms | 52 ms | 1122 ms |
从测试结果来看,默认自带sync效率很低,并且在测试时发现,采用sync方式在高并发时 会出现woker重启的情况, 如下:
[2015-06-25 11:31:06 +0000] [27040] [CRITICAL] WORKER TIMEOUT (pid:27064) [2015-06-25 11:31:06 +0000] [27040] [CRITICAL] WORKER TIMEOUT (pid:27051) [2015-06-25 11:31:06 +0000] [27040] [CRITICAL] WORKER TIMEOUT (pid:27045) [2015-06-25 11:31:06 +0000] [27040] [CRITICAL] WORKER TIMEOUT (pid:27046) [2015-06-25 11:31:06 +0000] [27064] [INFO] Worker exiting (pid: 27064) [2015-06-25 11:31:06 +0000] [27051] [INFO] Worker exiting (pid: 27051) [2015-06-25 11:31:06 +0000] [27045] [INFO] Worker exiting (pid: 27045) [2015-06-25 11:31:06 +0000] [27046] [INFO] Worker exiting (pid: 27046) [2015-06-25 11:31:06 +0000] [27263] [INFO] Booting worker with pid: 27263 [2015-06-25 11:31:06 +0000] [27264] [INFO] Booting worker with pid: 27264 [2015-06-25 11:31:06 +0000] [27277] [INFO] Booting worker with pid: 27277 [2015-06-25 11:31:06 +0000] [27280] [INFO] Booting worker with pid: 27280
eventlet 和gevent两种方式效果最好,数据基本差不多.