第一部分 Python3中性能测试工具Locust安装使用
概述
- Locust寓意蝗虫,蝗虫过境,寸草不生;而Locust工具生成并发请求就和一大群蝗虫一般,向我们的被测系统发起攻击,以此测试系统在高并发压力下是否能正常运转。
- Locust测试框架中,采用python进行开发,对常见的http(s)协议的系统,Locust采用request库作为客户端,在发请求时和request库使用方法一样。
- 在模拟并发时,Locust采用协程、非阻塞IO来实现网络层的并发请求,因此单台压力机也能产生数千并发请求,再加上对分布式运行的支持,Locust能在使用较少压力机的前提下支持极高的并发数测试。
Locust安装使用
安装
- python3中 --> pip3 install locust
- 验证是否安装成功 --> 终端中输入locust --help 显示帮助信息表示安装成功
- locust官网 --> https://www.locust.io/
- 大并发量测试时,建议在linux系统下进行
启动
1. 终端中 --> 进入到代码目录:
locust -f xxxx.py --host=xxxxx.com
- -f 指定性能测试脚本文件
- -host被测试应用的URL地址【如果不填写,读取继承(HttpLocust)类中定义的host】
2. 通过浏览器访问:http://localhost:8089(Locust启动网络监控器,默认端口号为:8089)
- Number of users to simulate 设置虚拟用户数
- Hatch rate(users spawned/second) 每秒产生(启动)的虚拟用户数,点击Start swarming按钮,开始运行性能测试。
3. 模式【no-web模式运行启动】
3.1 终端中 --> 进入代码目录:
locust -f xxoo.py --no-web -c10 -r2 -t 1m
--no-web 表示不使用web界面运行测试
-c 设置虚拟用户数
-r 设置每秒启动虚拟用户数
-t 设置运行时间
==no-web模式运行将测试结果保存到当前.py目录中:locust -f xxoo.py --csv=起一个名字==
3.2 例如:
locust -f test3.py --csv=foobar --no-web -c2 -t10s
4. 分布式压测
- 主从机中必须运行相同的测试代码(把主机中代码复制一份到多个从机中),主机负责收集测试数据,从机进行施压测试;
- 在主机终端中-->进入代码目录:>> locust -f xxxoo.py --master
- 从机中终端中-->进入代码目录:>> locust -f xxxoo.py --slave --master-host=主机ip
- 分布式压测no-web模式保存结果到主机中当前运行.py的目录中:>>locust -f test2.py --csv=foobartt --no-web -c2 -t10s --master locust --help 查看帮助信息
第二部分:记一次测试记录
最近应业务需要,在做压力测试,在测试工具的选型上,尝试了Loadrunner、Jmeter、Locust
后来对比后有如下结论:
- Loadrunner我装在mac电脑的pd虚拟机上,共享mac内存,但是效果并不太好,每秒启动用户数20个,这已经是最大启动用户数了,看来LR对压力机slave的性能要求过分依赖,果断弃用
- Jmeter在做小并发的负载测试时,感觉十分方便,特别是终端命令行模式运行,可以对服务器优化前后、代码缓存优化前后的结果有很好的对比,但是在这些宏观意义上的对比结束后,精确到细节,大并发的时候,jmeter感觉并不给力,同样运行在mac终端,启动20000个用户,基本上java的运行机制导致jmeter大部分完成不了这个并发启动用户数
- Locust:这个工具是基于Python安装的,很轻量,但是对于单机大并发来说,很给力,实际测试中,2000个用户以最大速率启动2000个用户,持续40秒钟,总request量已达20000+个,并且RPS(request per second)高达100+左右,相比于jmeter已经很给力了。
jmeter和locust对比
- 通过对比,明显发现在相近的request量下,jmeter的各项指标均大幅度低于locust压测的结果,说明在单就工具本身的压测能力上来说,locust > jmeter
locust测试:某业务接口
测试环境自身代码优化前后对比
说明(某业务接口-test_env):
- 优化前是啥都没改
- 优化配置是只增加单接口的缓存
- 优化各项缓存是增加了各环节的缓存
Locust脚本示例
"""
@author: xjy
@file: locust_study.py
@date: 2019/03/03 15:22:34
@email:
@IDE: PyCharm
@commitLog:
- 2019/3/3:
# code is far away from bugs with the god animal protecting
I love animals. They taste delicious.
┏┓ ┏┓
┏┛┻━━━┛┻┓
┃ ☃ ┃
┃ ┳┛ ┗┳ ┃
┃ ┻ ┃
┗━┓ ┏━┛
┃ ┗━━━┓
┃ 神兽保佑 ┣┓
┃ 永无BUG! ┏┛
┗┓┓┏━┳┓┏┛
┃┫┫ ┃┫┫
┗┻┛ ┗┻┛
"""
import logging
from locust import HttpLocust, TaskSet, task
# 去除警告用的,https下面使用的是verify=False
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class WebsitTasks(TaskSet):
def on_start(self): # 初始化的工作,每个locust用户开始做的第一件事
logging.info('--- User Start ---')
@task(1) # 这个装饰器的意思是:给每个人物设置权重,比如这个函数执行的权重就是1,如果下面是2,那么下面的函数就会更多的被执行
def enter_classroom(self):
# www环境
# with self.client.get('yyyyyy', catch_response=True) as response:
# pro环境
with self.client.get('yyyyy', catch_response=True,verify=False) as response:
if response.status_code == 200:
response.success()
print('-' * 50)
logging.info('返回值状态码为:%s' % response.status_code)
print('-' * 50)
else:
print('*' * 50)
response.failure('GetActConfig[Failed!]')
logging.error('错误请求,状态码为:', response.status_code)
print('*' * 50)
# @task(1)
# def yunlu(self):
# payload = {
# 'page': 1,
# 'per_page': 20
# }
# with self.client.get('/api/v1/mall/index', data=payload, catch_response=True) as response:
# if response.status_code == 200:
# response.success()
# else:
# response.failure('GetActConfig[Failed!]')
class WebsiteUser(HttpLocust):
# pro环境
host = 'xxxxxxxxxx' # 被测系统的host,在终端中启动locust时没有指定--host参数时才会用到
# www环境
# host = 'xxxxxxxxx' # 被测系统的host,在终端中启动locust时没有指定--host参数时才会用到
task_set = WebsitTasks # TaskSet类,该类定义用户人物信息,必填。这里就是:WebsiteTasks类名,因为该类集成TaskSet
min_wait = 0 # 每个用户执行两个任务间隔时间的上下限(毫秒),具体数值在上下限中随机取值,若不指定默认间隔时间固定为1秒
max_wait = 0
import os
if __name__ == '__main__':
# os.system('locust -f locust_study.py --csv=result --no-web -c2000 -r2000 -t40s --loglevel=INFO --logfile=test.log')
# 2000用户/2000/120s
os.system('locust -f locust_study.py --csv=result --no-web -c2000 -r2000 -t120s --loglevel=INFO --logfile=test.log')
# os.system('locust -f locust_study.py --csv=result --no-web -c10 -r10 -t5s --loglevel=INFO --logfile=test.log')
# os.system('locust -f locust_study.py')