续《深入浅出开源性能测试工具 Locust (使用篇 1)》
在开始运行Locust
脚本之前,我们先来看下Locust
支持的运行模式。
运行Locust
时,通常会使用到两种运行模式:单进程运行和多进程分布式运行。
单进程运行模式的意思是,Locust
所有的虚拟并发用户均运行在单个Python
进程中,具体从使用形式上,又分为no_web
和web
两种形式。该种模式由于单进程的原因,并不能完全发挥压力机所有处理器的能力,因此主要用于调试脚本和小并发压测的情况。
当并发压力要求较高时,就需要用到Locust
的多进程分布式运行模式。从字面意思上看,大家可能第一反应就是多台压力机同时运行,每台压力机分担负载一部分的压力生成。的确,Locust
支持任意多台压力机(一主多从)的分布式运行模式,但这里说到的多进程分布式运行模式还有另外一种情况,就是在同一台压力机上开启多个slave
的情况。这是因为当前阶段大多数计算机的 CPU 都是多处理器(multiple processor cores
),单进程运行模式下只能用到一个处理器的能力,而通过在一台压力机上运行多个slave
,就能调用多个处理器的能力了。比较好的做法是,如果一台压力机有N
个处理器内核,那么就在这台压力机上启动一个master
,N
个slave
。当然,我们也可以启动N
的倍数个slave
,但是根据我的试验数据,效果跟N
个差不多,因此只需要启动N
个slave
即可。
Locust
脚本编写完毕后,通常不会那么顺利,在正式开始性能测试之前还需要先调试运行下。
不过,Locust
脚本虽然为 Python 脚本,但却很难直接当做 Python 脚本运行起来,为什么呢?这主要还是因为Locust
脚本中引用了HttpLocust
和TaskSet
这两个类,如果要想直接对其进行调用测试,会发现编写启动脚本是一个比较困难的事情。因为这个原因,刚接触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.
如果slave
与master
不在同一台机器上,还需要通过--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.
master
和slave
都启动完毕后,就可以在浏览器中通过http://locust_machine_ip:8089
进入Locust
的 Web 管理页面了。使用方式跟单进程web
形式完全相同,只是此时是通过多进程负载来生成并发压力,在web
管理界面中也能看到实际的slave
数量。
Locust
在执行测试的过程中,我们可以在web
界面中实时地看到结果运行情况。
相比于LoadRunner
,Locust
的结果展示十分简单,主要就四个指标:并发数
、RPS
、响应时间
、异常率
。但对于大多数场景来说,这几个指标已经足够了。
在上图中,RPS
和平均响应时间
这两个指标显示的值都是根据最近 2 秒请求响应数据计算得到的统计值,我们也可以理解为瞬时值。
如果想看性能指标数据的走势,就可以在Charts
栏查看。在这里,可以查看到RPS
和平均响应时间
在整个运行过程中的波动情况。这个功能之前在Locust
中一直是缺失的,直到最近,这个坑才被我之前在阿里移动
的同事(网络 IDmyzhan
)给填上了。当前该功能已经合并到Locust
了,更新到最新版即可使用。
除了以上数据,Locust
还提供了整个运行过程数据的百分比统计值,例如我们常用的90%响应时间
、响应时间中位值
,该数据可以通过Download response time distribution CSV
获得,数据展示效果如下所示。
通过前面对Locust
全方位的讲解,相信大家对Locust
的功能特性已经非常熟悉了,在实际项目中将Locust
作为生产力工具应该也没啥问题了。
不过,任何一款工具都不是完美的,必定都会存在一些不足之处。但是好在Locust
具有极强的可定制型,当我们遇到一些特有的需求时,可以在Locust
上很方便地实现扩展。
还是前面提到的那位技术大牛(myzhan
),他为了摆脱CPython
的GIL
和gevent
的 monkey_patch()
,将Locust
的slave
端采用golang
进行了重写,采用goroutine
取代了gevent
。经过测试,相较于原生的Python
实现,他的这套golang
实现具有5~10
倍以上的性能提升。当前,他已经将该实现开源,项目名称为myzhan/boomer
,如果大家感兴趣,可以阅读他的博客文章进一步了解,《用 golang 来编写压测工具》。
如果我们也想在Locust
的基础上进行二次开发,那要怎么开始呢?
毫无疑问,阅读Locust
的项目源码是必不可少的第一步。可能对于很多人来说,阅读开源项目源码是一件十分困难的事情,不知道如何着手,在知乎上也看到好多关于如何阅读开源项目源码的提问。事实上,Locust
项目的代码结构清晰,核心代码量也比较少,十分适合阅读学习。哪怕只是想体验下阅读开源项目源码,或者说想提升下自己的Python
技能,Locust
也是个不错的选择。
在下一篇文章中,我将对Locust
源码进行解析,《深入浅出开源性能测试工具 Locust(源码篇)》,敬请期待!
Stormer:https://github.com/debugtalk/Stormer
欢迎关注我的个人博客和微信公众号。
DebugTalk