《深入浅出开源性能测试工具 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中执行命令进行启动的,通用的参数有如下两个:

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

单进程运行

no_web

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

$ 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;如果要使用其它端口,就可以使用如下参数进行指定。

$ 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管理页面中,需要配置的参数只有两个:

参数配置完毕后,点击【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

硬广

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


↙↙↙阅读原文可查看相关链接,并与作者交流