Gunicorn性能测试

前言

写了很多很多Flask的API, 但是一直偷懒, 没有使用Gunicorn来作为Web Server 来运行成。

后来因为某个线上服务, 经常出现timeout的情况。 在已经采用了好一些措施的情况还是无法完全避免的情况下, 想到了Gunicorn。

下面是迁移之前进行的一些简单的性能测试。 真正迁移其实比下面的脚本要复杂一些。

Gunicorn安全与测试命令

安装Gunicorn

安装与运行很简单,直接pip命令即可:

性能测试工具: wrk

Linux安装官网地址: https://github.com/wg/wrk/wiki/Installing-Wrk-on-Linux

对于Ubuntu / Debian :

wrk 使用简单说明:

测试的Flask 程序

这里为了简单, 主要测试python将一段string变成json的逻辑

数据来源: https://itunes.apple.com/search?term=apple

为了保持代码逻辑清晰, 将其中的json字符串“隐藏了”

注意: 前端使用nginx做了转发。nginx配置如下:

这样,我们就可以通过nginx转发的域名来做性能测试了。
PS: nginx主要解决静态文件+慢客户端的问题, 在这里对性能测试的影响应该不大。

测试1: 使用Flask内置的server进行测试

测试命令:

测试结果:

测试小结:

需要注意的数字:

  1. 一共产生了472个requests
  2. 一共出现了248次timeout, 这个比例相当高了, 比例: 52.5%
  3. 平均访问延时: 794.04ms

测试2: 使用Gunicorn 单核

测试命令:

测试结果:

测试小结:

timeout 比例: 187 / 475 = 39.3%

可以看到, 比例下降非常明显。 平均访问延时也从794 下降到 765ms, 提升 (794 – 765) / 794 = 3%

测试3: 使用Gunicorn 双核

毕竟我们的服务有两个核, 之前的测试也一直没有把单核占满!

测试命令:

测试结果:

测试小结:

不出意外, 性能进一步提升, 而且很明显。

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来包装使用, 就很简单了。具体请看下面的测试命令

测试命令:

测试结果:

测试小结:

timeout 比例: 174 / 484 = 35.95% , 虽然不及双核的表现, 但是相比Gunicorn默认单核, 还是有所提升的

平均访问延时也从765 下降到 737ms。

测试4: Gunicorn + Gevent 双核

这个应该是最强搭配了

测试命令:

测试结果:

测试小结:

  1. 相比测试3,使用原生双核, 很意外, 平均延时有所上升, 从556上升到现在591
  2. 但是总体的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性能测试

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注