性能测试工具 深入浅出开源性能测试工具 Locust (使用篇 2)

debugtalk · 2017年02月23日 · 最后由 皮大大的豆花皮 回复于 2022年02月11日 · 10041 次阅读

《深入浅出开源性能测试工具 Locust (使用篇 1)》

Locust 运行模式

在开始运行Locust脚本之前,我们先来看下Locust支持的运行模式。

运行Locust时,通常会使用到两种运行模式:单进程运行和多进程分布式运行。

单进程运行模式的意思是,Locust所有的虚拟并发用户均运行在单个Python进程中,具体从使用形式上,又分为no_webweb两种形式。该种模式由于单进程的原因,并不能完全发挥压力机所有处理器的能力,因此主要用于调试脚本和小并发压测的情况。

当并发压力要求较高时,就需要用到Locust的多进程分布式运行模式。从字面意思上看,大家可能第一反应就是多台压力机同时运行,每台压力机分担负载一部分的压力生成。的确,Locust支持任意多台压力机(一主多从)的分布式运行模式,但这里说到的多进程分布式运行模式还有另外一种情况,就是在同一台压力机上开启多个slave的情况。这是因为当前阶段大多数计算机的 CPU 都是多处理器(multiple processor cores),单进程运行模式下只能用到一个处理器的能力,而通过在一台压力机上运行多个slave,就能调用多个处理器的能力了。比较好的做法是,如果一台压力机有N个处理器内核,那么就在这台压力机上启动一个masterNslave。当然,我们也可以启动N的倍数个slave,但是根据我的试验数据,效果跟N个差不多,因此只需要启动Nslave即可。

脚本调试

Locust脚本编写完毕后,通常不会那么顺利,在正式开始性能测试之前还需要先调试运行下。

不过,Locust脚本虽然为 Python 脚本,但却很难直接当做 Python 脚本运行起来,为什么呢?这主要还是因为Locust脚本中引用了HttpLocustTaskSet这两个类,如果要想直接对其进行调用测试,会发现编写启动脚本是一个比较困难的事情。因为这个原因,刚接触Locust的同学可能就会觉得Locust脚本不好调试。

但这个问题也能克服,那就是借助Locust的单进程no_web运行模式。

Locust的单进程no_web运行模式中,我们可以通过--no-web参数,指定并发数(-c)和总执行次数(-n),直接在Terminal中执行脚本。

在此基础上,当我们想要调试Locust脚本时,就可以在脚本中需要调试的地方通过print打印日志,然后将并发数和总执行次数都指定为 1,执行形式如下所示。

$ locust -f locustfile.py --no-web -c 1 -n 1

通过这种方式,我们就能很方便地对Locust脚本进行调试了。

执行测试

Locust脚本调试通过后,就算是完成了所有准备工作,可以开始进行压力测试了。

Locust是通过在Terminal中执行命令进行启动的,通用的参数有如下两个:

  • -H, --host:被测系统的host,若在Terminal中不进行指定,就需要在Locust子类中通过host参数进行指定;
  • -f, --locustfile:指定执行的Locust脚本文件;

除了这两个通用的参数,我们还需要根据实际测试场景,选择不同的Locust运行模式,而模式的指定也是通过其它参数来进行控制的。

单进程运行

no_web

如果采用no_web形式,则需使用--no-web参数,并会用到如下几个参数。

  • -c, --clients:指定并发用户数;
  • -n, --num-request:指定总执行测试;
  • -r, --hatch-rate:指定并发加压速率,默认值位 1。
$ locust -H http://debugtalk.com -f demo.py --no-web -c1 -n2
[2017-02-21 21:27:26,522] Leos-MacBook-Air.local/INFO/locust.main: Starting Locust 0.8a2
[2017-02-21 21:27:26,523] Leos-MacBook-Air.local/INFO/locust.runners: Hatching and swarming 1 clients at the rate 1 clients/s...
 Name                                                          # reqs      # fails     Avg     Min     Max  |  Median   req/s
--------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------
 Total                                                              0     0(0.00%)                                       0.00

[2017-02-21 21:27:27,526] Leos-MacBook-Air.local/INFO/locust.runners: All locusts hatched: WebsiteUser: 1
[2017-02-21 21:27:27,527] Leos-MacBook-Air.local/INFO/locust.runners: Resetting stats

 Name                                                          # reqs      # fails     Avg     Min     Max  |  Median   req/s
--------------------------------------------------------------------------------------------------------------------------------------
 GET /about/                                                        0     0(0.00%)       0       0       0  |       0    0.00
--------------------------------------------------------------------------------------------------------------------------------------
 Total                                                              0     0(0.00%)                                       0.00

 Name                                                          # reqs      # fails     Avg     Min     Max  |  Median   req/s
--------------------------------------------------------------------------------------------------------------------------------------
 GET /about/                                                        1     0(0.00%)      17      17      17  |      17    0.00
--------------------------------------------------------------------------------------------------------------------------------------
 Total                                                              1     0(0.00%)                                       0.00

[2017-02-21 21:27:32,420] Leos-MacBook-Air.local/INFO/locust.runners: All locusts dead

[2017-02-21 21:27:32,421] Leos-MacBook-Air.local/INFO/locust.main: Shutting down (exit code 0), bye.
 Name                                                          # reqs      # fails     Avg     Min     Max  |  Median   req/s
--------------------------------------------------------------------------------------------------------------------------------------
 GET /                                                              1     0(0.00%)      20      20      20  |      20    0.00
 GET /about/                                                        1     0(0.00%)      17      17      17  |      17    0.00
--------------------------------------------------------------------------------------------------------------------------------------
 Total                                                              2     0(0.00%)                                       0.00

Percentage of the requests completed within given times
 Name                                                           # reqs    50%    66%    75%    80%    90%    95%    98%    99%   100%
--------------------------------------------------------------------------------------------------------------------------------------
 GET /                                                               1     20     20     20     20     20     20     20     20     20
 GET /about/                                                         1     17     17     17     17     17     17     17     17     17
--------------------------------------------------------------------------------------------------------------------------------------

web

如果采用web形式,,则通常情况下无需指定其它额外参数,Locust默认采用8089端口启动web;如果要使用其它端口,就可以使用如下参数进行指定。

  • -P, --port:指定 web 端口,默认为8089.
$ locust -H http://debugtalk.com -f demo.py
[2017-02-21 21:31:26,334] Leos-MacBook-Air.local/INFO/locust.main: Starting web monitor at *:8089
[2017-02-21 21:31:26,334] Leos-MacBook-Air.local/INFO/locust.main: Starting Locust 0.8a2

此时,Locust并没有开始执行测试,还需要在 Web 页面中配置参数后进行启动。

如果Locust运行在本机,在浏览器中访问http://localhost:8089即可进入Locust的 Web 管理页面;如果Locust运行在其它机器上,那么在浏览器中访问http://locust_machine_ip:8089即可。

Locust的 Web 管理页面中,需要配置的参数只有两个:

  • Number of users to simulate: 设置并发用户数,对应中no_web模式的-c, --clients参数;
  • Hatch rate (users spawned/second): 启动虚拟用户的速率,对应着no_web模式的-r, --hatch-rate参数。

参数配置完毕后,点击【Start swarming】即可开始测试。

多进程分布式运行

不管是单机多进程,还是多机负载模式,运行方式都是一样的,都是先运行一个master,再启动多个slave

启动master时,需要使用--master参数;同样的,如果要使用8089以外的端口,还需要使用-P, --port参数。

$ locust -H http://debugtalk.com -f demo.py --master --port=8088
[2017-02-21 22:59:57,308] Leos-MacBook-Air.local/INFO/locust.main: Starting web monitor at *:8088
[2017-02-21 22:59:57,310] Leos-MacBook-Air.local/INFO/locust.main: Starting Locust 0.8a2

master启动后,还需要启动slave才能执行测试任务。

启动slave时需要使用--slave参数;在slave中,就不需要再指定端口了。

$ locust -H http://debugtalk.com -f demo.py --slave
[2017-02-21 23:07:58,696] Leos-MacBook-Air.local/INFO/locust.main: Starting Locust 0.8a2
[2017-02-21 23:07:58,696] Leos-MacBook-Air.local/INFO/locust.runners: Client 'Leos-MacBook-Air.local_980ab0eec2bca517d03feb60c31d6a3a' reported as
 ready. Currently 2 clients ready to swarm.

如果slavemaster不在同一台机器上,还需要通过--master-host参数再指定master的 IP 地址。

$ locust -H http://debugtalk.com -f demo.py --slave --master-host=<locust_machine_ip>
[2017-02-21 23:07:58,696] Leos-MacBook-Air.local/INFO/locust.main: Starting Locust 0.8a2
[2017-02-21 23:07:58,696] Leos-MacBook-Air.local/INFO/locust.runners: Client 'Leos-MacBook-Air.local_980ab0eec2bca517d03feb60c31d6a3a' reported as
 ready. Currently 2 clients ready to swarm.

masterslave都启动完毕后,就可以在浏览器中通过http://locust_machine_ip:8089进入Locust的 Web 管理页面了。使用方式跟单进程web形式完全相同,只是此时是通过多进程负载来生成并发压力,在web管理界面中也能看到实际的slave数量。

测试结果展示

Locust在执行测试的过程中,我们可以在web界面中实时地看到结果运行情况。

相比于LoadRunnerLocust的结果展示十分简单,主要就四个指标:并发数RPS响应时间异常率。但对于大多数场景来说,这几个指标已经足够了。

在上图中,RPS平均响应时间这两个指标显示的值都是根据最近 2 秒请求响应数据计算得到的统计值,我们也可以理解为瞬时值。

如果想看性能指标数据的走势,就可以在Charts栏查看。在这里,可以查看到RPS平均响应时间在整个运行过程中的波动情况。这个功能之前在Locust中一直是缺失的,直到最近,这个坑才被我之前在阿里移动的同事(网络 IDmyzhan)给填上了。当前该功能已经合并到Locust了,更新到最新版即可使用。

除了以上数据,Locust还提供了整个运行过程数据的百分比统计值,例如我们常用的90%响应时间响应时间中位值,该数据可以通过Download response time distribution CSV获得,数据展示效果如下所示。

总结

通过前面对Locust全方位的讲解,相信大家对Locust的功能特性已经非常熟悉了,在实际项目中将Locust作为生产力工具应该也没啥问题了。

不过,任何一款工具都不是完美的,必定都会存在一些不足之处。但是好在Locust具有极强的可定制型,当我们遇到一些特有的需求时,可以在Locust上很方便地实现扩展。

还是前面提到的那位技术大牛(myzhan),他为了摆脱CPythonGILgeventmonkey_patch(),将Locustslave端采用golang进行了重写,采用goroutine取代了gevent。经过测试,相较于原生的Python实现,他的这套golang实现具有5~10倍以上的性能提升。当前,他已经将该实现开源,项目名称为myzhan/boomer,如果大家感兴趣,可以阅读他的博客文章进一步了解,《用 golang 来编写压测工具》

如果我们也想在Locust的基础上进行二次开发,那要怎么开始呢?

毫无疑问,阅读Locust的项目源码是必不可少的第一步。可能对于很多人来说,阅读开源项目源码是一件十分困难的事情,不知道如何着手,在知乎上也看到好多关于如何阅读开源项目源码的提问。事实上,Locust项目的代码结构清晰,核心代码量也比较少,十分适合阅读学习。哪怕只是想体验下阅读开源项目源码,或者说想提升下自己的Python技能,Locust也是个不错的选择。

在下一篇文章中,我将对Locust源码进行解析,《深入浅出开源性能测试工具 Locust(源码篇)》,敬请期待!

GitHub 项目地址

Stormer:https://github.com/debugtalk/Stormer

硬广

欢迎关注我的个人博客和微信公众号。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 46 条回复 时间 点赞
47楼 已删除

pip install locustio==0.8a2 要更新这个版本;更新了也没有 charts,望楼主回复下;

kilalonger 回复

更好的方式是,直接从 github 项目源码进行安装。

$ pip install git+git://github.com/locustio/locust.git@master#egg=locustio
debugtalk 回复

嗯 已提示最新 但 web 端依然没有 charts 真奇怪;

kilalonger 回复

通过 pypi 安装的包都会滞后些,哪怕版本号相同,但是跟源码 master 分支的最新代码还是可能不一致的

debugtalk 回复

ok 我缓缓再看看 感谢

提到的myzhan/boomer这个思路不错,我本打算直接用 golang 整个重写 locust 的
如果全部用 golang 重写的话,我测过单机大约能产生 45K QPS 的压力
远大于 locust 8 个节点约 4K QPS 的能力

jacexh 回复

你说的 8 个节点是 8 个 slave 进程的意思么?

debugtalk 回复

是的

jacexh 回复

你是怎么测的单机并发能力啊?可否分享下?

可以准备两台服务器,服务器 A 作为施压方,服务器 B 作为承压方
服务器 B 上简单的运行一个 nginx 服务就行了

服务器 A 上可以安装一些常用的压测工具,比如 locust、ab、wrk

我当时测下来,施压能力上 wrk > golang >> ab > locust

因为 locust 一个进程只使用一核 CPU,所以用 locust 压测时,必须使用主从分布式(zeromq 通讯)模式,并根据服务器 CPU 核数来起 slave 节点数

wrk 约为 55K QPS
golang net/http 约 45K QPS
ab 大约 15K QPS
locust 最差,而且 response time 明显不正常

jacexh 回复

谢谢啦!

很详细,这工具就是定制好上手,最初我也选过 locust,但压测结果与 ab 差的有点多,感觉不是很准。

衔尾蛇 回复

那你是怎么确定是 locust 的结果不准,而不是 ab 呢?

debugtalk 回复

少说了俩,还有 jmeter 和 siege;
当年选工具的时候做的对比,拿同样的数据和并发做了简单的对比,ab 的数据是最漂亮的,siege 和 jmeter 两者数据差距不大,Locust 出来的数据,平均的响应时间比其他几个多很多;jmeter 和 locust 都是一台 master 一台 slave 从的测。现在想想有可能是没考虑到 CPU 核心数与 slave 数的关系导致的。

衔尾蛇 回复

多谢!改天我也来搞个 benchmark 测试看看

jacexh 回复

在测试过程中有没有将所有工具都禁止 Keepalive?如果重用连接的话 QPS 会高出许多

我测试了一下,locust 的性能太差了,比别的工具差一两个数量级

衔尾蛇 回复

你可以用 jmeter -g test.jtl -o 来生成报表,报表也很漂亮

相反,我认为压测时应该开启连接复用 (keepalive)——是压服务的处理能力,不要把时间浪费在 TCP 握手上面
所以 ab 这种工具有很致命的缺陷

jacexh 回复

像 ab 和 http_load 发送的都是 HTTP/1.0 协议,默认需要服务器断开连接,开发它们的人不知是怎样考虑的
ab 使用-k 参数也可以实现 Keepalive 吧?
我测了一下,性能还可以,50k 也能达到

楼主必须用 python2 吗

没有限制

目前使用的是 0.8a2,参数中没有--no_web,而是--no-web.望更新.

--更新--
看了下面的单线程,写的是对的.
上面的
$ locust -f locustfile.py --no_web -c 1 -n 1
需要修改,o(╯□╰) o

one.way 回复

已修改,感谢指正

debugtalk 回复

看完了 2 篇,发现没讲集合点.😂

one.way 回复

“集合点” 的概念确实在现在的性能测试中淡出了,更在乎的是一个系统/接口的处理能力(TPS/QPS),这个处理能力偏向于 keepalive 状态下连续不断的请求和响应。

果冻 回复

是想了解 locust 支不支持这个功能.

one.way 回复

不支持

debugtalk 回复

了解,谢谢.

jacexh 回复

压力源(wrk):24 核 CPU,万兆网卡,125G 内存
服务器(Nginx):24 核 CPU,万兆网卡,125G 内存
测试结果:在 Nginx 未做任何调优的情况下,压测一个小于 1KB 的静态页,wrk 可达到 45 万 QPS

Nginx 的 CPU 资源耗尽:

jacexh 回复

你好,可以 加个好友吗?探讨一下 wrk 的二次开发

jacexh 回复

方便的话,加一下好友讨论一下 wrk 的二次开发问题吧 QQ:851462306

在路上 回复

这机器配置真实强大,wrt 表现也非常牛逼
但是 nginx 的配置我建议还可以继续优化: 不用读静态文件,直接 return 字符串

jacexh 回复

我们公司已经对 wrk 做了二次开发,功能相当齐全了

jacexh 回复

有对 grinder 做过性能对比吗?据说性能是 jmeter 的十倍,但是我测试发现,跟 jmeter 差不多,不知道是不是我的使用问题

晚上回去加 QQ 😏
我目前基于 golang 实现了一套通用的性能测试工具, https://github.com/jacexh/ultron
理论支持任何协议,当然了,单实例性能肯定会弱于 wrk,不过好在改成分布式也很方便

嘿嘿,大神,那个如果使用那个 locust 做压测他的值怎么进行返回和传递呢?直接打印出来没有值得?

如果是加密的接口,该怎么去处理

回复

在 Locust 中,所有的脚本都只是 Python 而已,所以你只需要采用 Python 描述你的业务逻辑就好了。

我是老罗 回复

通常的做法是,发起请求时调用加密算法来构造请求数据,前提还是你得知道加密算法。

debugtalk 回复

按这样说岂不是构造的数据必须从真实数据库捞出的真实数据进行加密处理,这样的话高并发时造数据也是非常必要的工作?

问下大神如果要压 TCP 协议的有木有什么方法去扩展

楼主,怎么分析性能测试报告呀,有没有什么推荐书籍或文章可学习的?目前看了文章后,会用上 locust 了但不会分析结果。感谢🙏 🙏

匿名 #2 · 2018年03月23日

强烈支持源码篇啊 什么时候可以放出来啊

测试结果展示为啥我显示不出你发的图片呢,只能看到贴出来的代码

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册