内容简介:写了很多很多Flask的API, 但是一直偷懒, 没有使用Gunicorn来作为Web Server 来运行成。后来因为某个线上服务, 经常出现timeout的情况。 在已经采用了好一些措施的情况还是无法完全避免的情况下, 想到了Gunicorn。
前言
写了很多很多Flask的API, 但是一直偷懒, 没有使用Gunicorn来作为Web Server 来运行成。
后来因为某个线上服务, 经常出现timeout的情况。 在已经采用了好一些措施的情况还是无法完全避免的情况下, 想到了Gunicorn。
下面是迁移之前进行的一些简单的性能测试。 真正迁移其实比下面的脚本要复杂一些。
Gunicorn安全与测试命令
安装Gunicorn
安装与运行很简单,直接pip命令即可:
pip install gunicorn # 安装Gunicorn pip install gunicorn[gevent] # 安装 gevent组件, 尝试多核
性能测试工具: wrk
Linux安装官网地址: https://github.com/wg/wrk/wiki/Installing-Wrk-on-Linux
对于Ubuntu / Debian :
sudo apt-get install build-essential libssl-dev git -y git clone https://github.com/wg/wrk.git wrk cd wrk sudo make # move the executable to somewhere in your PATH, ex: sudo cp wrk /usr/local/bin
wrk 使用简单说明:
# 格式: wrk -d20s -t10 -c200 [url] # -d: duration 测试持续时间 # -t: threads 线程数 # -c: connection 连接数
测试的Flask 程序
这里为了简单, 主要测试 python 将一段string变成json的逻辑
数据来源: https://itunes.apple.com/search?term=apple
为了保持代码逻辑清晰, 将其中的json字符串“隐藏了”
# perf_test.py import json from flask import Flask, jsonify app = Flask(__name__) @app.route('/') def index(): return 'hello world' @app.route('/performance_test_json') def performance_test_json() : raw_json = """ # please paste json content from: https://itunes.apple.com/search?term=apple """.strip() raw_json = json.loads(raw_json ) return jsonify( raw_json ) if __name__ == '__main__': app.debug = False app.run(port=5001)
注意: 前端使用nginx做了转发。nginx配置如下:
server { listen 80; server_name my-test-domain.com; client_max_body_size 5M; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:5001; } access_log logs/my-test-domain.com.access.log; }
这样,我们就可以通过nginx转发的域名来做性能测试了。
PS: nginx主要解决静态文件+慢客户端的问题, 在这里对性能测试的影响应该不大。
测试1: 使用Flask内置的server进行测试
测试命令:
# 启动flask的命令 python perf_test.py # wrk命令 wrk -d20s -t10 -c200 http://my-test-domain.com/performance_test_json
测试结果:
Running 20s test @ http://my-test-domain.com/performance_test_json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 794.04ms 601.06ms 1.98s 55.36% Req/Sec 5.17 11.44 202.00 97.43% 472 requests in 20.04s, 4.46MB read Socket errors: connect 0, read 0, write 0, timeout 248 Requests/sec: 23.55 Transfer/sec: 227.83KB
测试小结:
需要注意的数字:
- 一共产生了472个requests
- 一共出现了248次timeout, 这个比例相当高了, 比例: 52.5%
- 平均访问延时: 794.04ms
测试2: 使用Gunicorn 单核
测试命令:
# 使用Gunicorn启动Flask gunicorn -w 1 -b 127.0.0.1:5001 perf_test:app # 注意:这里使用的是单核哦 # wrk命令 wrk -d20s -t10 -c200 http://my-test-domain.com/performance_test_json
测试结果:
Running 20s test @ http://my-test-domain.com/performance_test_json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 765.60ms 589.04ms 1.99s 61.11% Req/Sec 5.14 11.79 202.00 96.52% 475 requests in 20.04s, 4.49MB read Socket errors: connect 0, read 0, write 0, timeout 187 Requests/sec: 23.71 Transfer/sec: 229.41KB
测试小结:
timeout 比例: 187 / 475 = 39.3%
可以看到, 比例下降非常明显。 平均访问延时也从794 下降到 765ms, 提升 (794 – 765) / 794 = 3%
测试3: 使用Gunicorn 双核
毕竟我们的服务有两个核, 之前的测试也一直没有把单核占满!
测试命令:
# 使用Gunicorn启动Flask gunicorn -w 2 -b 127.0.0.1:5001 perf_test:app # 注意:这里使用的是【双核】哦 # wrk命令 wrk -d20s -t10 -c200 http://my-test-domain.com/performance_test_json
测试结果:
Running 20s test @ http://my-test-domain.com/performance_test_json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 556.30ms 506.81ms 1.98s 66.58% Req/Sec 6.47 11.28 202.00 93.03% 530 requests in 20.04s, 4.69MB read Socket errors: connect 0, read 0, write 0, timeout 132 Requests/sec: 26.45 Transfer/sec: 239.71KB
测试小结:
不出意外, 性能进一步提升, 而且很明显。
timeout比例: 132 / 530 = 24.9%
平均延时也下降到 556ms
测试3: 使用Gunicorn 单核 + Gevent
Gevent + Gunicorn 应该是一个很常见的组合。
什么是Gevent?
From : 廖雪峰的官方网站
Python通过 yield
提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。
gevent是第三方库,通过greenlet实现协程,其基本思想是:
当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
直接使用Gevent其实还是要花一些时间, 不过让Gunicorn来包装使用, 就很简单了。具体请看下面的测试命令
测试命令:
# 使用Gunicorn启动Flask pip install gunicorn[gevent] # 确保安装了gevent gunicorn -w 1 -k gevent -b 127.0.0.1:5001 perf_test:app # 注意:这里使用的是单核哦 # wrk命令 wrk -d20s -t10 -c200 http://my-test-domain.com/performance_test_json
测试结果:
Running 20s test @ http://my-test-domain.com/performance_test_json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 737.19ms 579.67ms 1.98s 59.03% Req/Sec 5.90 14.47 230.00 98.97% 484 requests in 20.04s, 4.55MB read Socket errors: connect 0, read 0, write 0, timeout 174 Requests/sec: 24.15 Transfer/sec: 232.38KB
测试小结:
timeout 比例: 174 / 484 = 35.95% , 虽然不及双核的表现, 但是相比Gunicorn默认单核, 还是有所提升的
平均访问延时也从765 下降到 737ms。
测试4: Gunicorn + Gevent 双核
这个应该是最强搭配了
测试命令:
# 使用Gunicorn启动Flask pip install gunicorn[gevent] # 确保安装了gevent gunicorn -w 2 -k gevent -b 127.0.0.1:5001 perf_test:app # 注意:这里使用的是【双核】哦 # wrk命令 wrk -d20s -t10 -c200 http://my-test-domain.com/performance_test_json
测试结果:
Running 20s test @ http://my-test-domain.com/performance_test_json 10 threads and 200 connections Thread Stats Avg Stdev Max +/- Stdev Latency 591.00ms 543.56ms 1.97s 64.10% Req/Sec 6.79 13.67 181.00 98.77% 537 requests in 20.06s, 4.79MB read Socket errors: connect 0, read 0, write 0, timeout 122 Requests/sec: 26.77 Transfer/sec: 244.58KB
测试小结:
- 相比测试3,使用原生双核, 很意外, 平均延时有所上升, 从556上升到现在591
- 但是总体的timeout还是有所下降, 从132 下降到122
整体测试小结
上面的测试结果小结如下:
- Gunicorn 比原生的内置server 性能要快, 平均延时提升3%。 timeout的比例大大下降, 减少了约20%
- Gunicorn双核的表现要比单核强不少, 平均延时又减少了 20% 这样, timeout的比例也减少了约 40%
- Gevent 单核 比Gunicorn原生单核略强, 双核的表现可能跟测试用例有关, 表现并不明显
测试结果数据汇总
测试项目 | 平均延时(ms) | Timeout数量 | Timeout 比例 |
---|---|---|---|
Flask内置Server | 794 | 248 | 52.5% |
Gunicorn 单核 | 765 | 187 | 39.3% |
Gunicorn 双核 | 556 | 132 | 24.9% |
Gunicorn + Gevent 单核 | 737 | 174 | 35.9% |
Gunicorn + Gevent 双核 | 591 | 122 | 22.7% |
测试后记:
因为之前我们的程序设计到登录, 而且登录的Session在进程内存之中, 没使用 Redis 来管理。 因此理论上来说只能单核进行。
所以最后采用的方案: Gunicorn + Gevent 单核
估计还会有下文: 如何迁移你的Flask程序 (因为当前的Flask的启动设定比较多, 直接使用Gunicorn启动甚至会发生无法访问的情况。。。)
本文原创,转载需要注明出处
以上所述就是小编给大家介绍的《Gunicorn性能测试》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 微服务测试之性能测试
- Go 单元测试和性能测试
- 性能测试vs压力测试vs负载测试
- SpringBoot | 第十三章:测试相关(单元测试、性能测试)
- Golang 性能测试 (2) 性能分析
- 随行付微服务测试之性能测试 原 荐
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Intersectional Internet
Safiya Umoja Noble、Brendesha M. Tynes / Peter Lang Publishing / 2016
From race, sex, class, and culture, the multidisciplinary field of Internet studies needs theoretical and methodological approaches that allow us to question the organization of social relations that ......一起来看看 《The Intersectional Internet》 这本书的介绍吧!