Locust简介:
官网地址:Locust - A modern load testing framework
Locust是易于使用,可编写脚本且可扩展的性能测试工具。
特征
-
用普通的Python编写用户测试方案
如果要让用户循环,执行某些条件行为或进行一些计算,则只需使用Python提供的常规编程结构即可。Locust在其自己的greenlet(轻量级进程/协程)中运行每个用户。这使您可以像编写普通(阻塞)Python代码一样编写测试,而不必使用回调或其他某种机制。因为您的场景是“仅是python”,所以您可以使用常规的IDE,并以常规代码的形式控制测试(与其他一些使用XML或二进制格式的工具相对)
-
分布式和可扩展-支持数十万用户
Locust使运行分布在多台计算机上的负载测试变得容易。它是基于事件的(使用gevent),这使得单个进程可以处理成千上万的并发用户。尽管可能还有其他工具可以在给定的硬件上每秒执行更多请求,但是每个Locust用户的低开销使其非常适合测试高并发工作负载。
-
基于Web的UI
Locust具有用户友好的Web界面,可实时显示测试进度。您甚至可以在测试运行时更改负载。它也可以在没有UI的情况下运行,从而易于进行CI / CD测试。
-
可以测试任何系统
开始使用:
# 最简单的使用
from locust import HttpUser, task, between, TaskSet
import os
# 接口请求任务类 继承TaskSet
class MyTask(TaskSet):
@task(1) # 设置任务权重,当有多个任务(接口)时
def suerinfo(self):
data = {}
# 使用 self.client 代替requests 进行接口请求
res = self.client.post(url="/api/config/list", json=data)
print(res.json())
class User(HttpUser):
host = "http://yuming.com"
wait_time = between(0.1, 0.5)
tasks = [MyTask, ]
if __name__ == '__main__':
os.system("locust -f locust_demo.py")
# 浏览器访问 http://localhost:8090 打开web测试页面
# 多任务,自定义接口状态(成功、失败)
from locust import HttpUser, task, TaskSet
# 测试任务设置(设置不同的接口请求)
class HelloWorld(TaskSet):
@task
def hello(self):
with self.client.get(url="/", catch_response=True, name="/") as response:
if response.status_code == 200:
# 标记请求失败,哪怕请求是成功的
response.failure("自定义失败")
@task
def world(self):
# 使用 catch_response=True 来截取接口返回数据
with self.client.get(url="/index", name="/index", catch_response=True) as response:
if response.status_code != 200:
# 标记请求成功,哪怕接口实际是失败的
response.success()
# 测试场景设置(用来模拟不同测试场景:包括要执行的任务类,任务运行之间的等待时间,域名以及其他配置)
class WebUser(HttpUser):
# 指定测试任务类
tasks = [HelloWorld, ]
# 设置每个用户在多个接口请求之间的等待延迟时间 单位:秒
min_wait = 1
max_wait = 2
# 请求域名
host = "http://www.rjcs.top"
if __name__ == '__main__':
import os
os.system("locust -f demo_locust_one.py --headless -u 1 -r 1 -t 5s")
定义任务类 class MyTask(TaskSet): 继承TaskSet.
内置了三个等待时间功能:模拟用户在每个任务执行后的等待时间,单位:秒。如果没有指定任务之间的延迟时间,就会在上一个任务执行后立即执行下一个任务。
-
constant 在固定的时间内
-
between 在最大值和最小值之间的随机时间
-
constant_pacing 自适应时间,以确保任务每X秒(最多)运行一次
@task(1) # 有多个任务/接口时,可以使用@task() 标记执行权重;
HttpUser 类 为每个用户提供一个client属性,client 是一个 HttpSession 的实例,HttpSession 是requests.Session 的子类。
HttpSession 主要是将请求结果上报到 Locust 中(成功/失败、响应时间、响应长度、名称)
定义任务方法一:
使用 @task装饰器 来声明任务。当有多个任务并且没有指定权重时,任务时随机执行的;
当使用@task(权重数字)声明权重后,根据权重比例执行
定义任务方法二:
tasks = [task1, task2] # 任务权重随机
tasks = ["task1":1, "task2": 2] # 指定任务权重
self.client.get("/hello") self.client.post("/hello") 接口调用
# name属性用来分组,在统计数据中按照一类请求进行统计
self.client.get(f"/item?id={item_id}", name="/item")
on_start和on_stop方法
HttpUser类(和TaskSet类)可以声明一个on_start方法和/或 on_stop方法。每个用户在启动时和退出时都会调用。相当于pytest内的setup、teardown.
标记tag,可指定运行指定的tag
使用@tag("tag name")标记任务,然后使用 --tags tagname1 tagname2 来运行指定标记的tag任务
如果使用 --exclude-tags tagname1 tagname2命令,不会运行tagname1 tagname2标记的任务
# 标记请求成功/失败 response.success() response.failure()
with self.client.get("/", catch_response=True) as response:
if response.text != "Success":
response.failure("Got wrong response")
elif response.elapsed.total_seconds() > 0.5:
response.failure("Request took too long")
# 对多个不同的同类型请求任务进行分组 client.rename_request("groupname")
@task
def multiple_groupings_example(self):
# Statistics for these requests will be grouped under: /blog/?id=[id]
with self.client.rename_request("/blog?id=[id]"):
for i in range(10):
self.client.get("/blog?id=%i" % i)
# Statistics for these requests will be grouped under: /article/?id=[id]
with self.client.rename_request("/article?id=[id]"):
for i in range(10):
self.client.get("/article?id=%i" % i)
运行:
命令行使用:locust -f locust_test.py 具体详细见--help
web 浏览器页面访问地址 http://localhost:8089 (http://127.0.0.1:8089可能不生效)
命令行内 | 环境变量 | 配置文件内 | 描述 |
|
|
| 要导入的 Python 模块文件,例如“../other.py”。默认值:locustfile |
|
|
| 主机按以下格式进行负载测试:http : //10.21.32.33 |
|
|
| 并发 Locust 用户的峰值数量。主要与 –headless 或 –autostart 一起使用。可以在测试期间通过键盘输入 w、W(生成 1、10 个用户)和 s、S(停止 1、10 个用户)更改 |
|
|
| 产生用户的速率(每秒用户数)。主要与 –headless 或 –autostart 一起使用 |
|
|
| ==抑制== |
|
|
| 在指定的时间后停止,例如(300s、20m、3h、1h30m 等)。仅与 –headless 或 –autostart 一起使用。默认永远运行。 |
|
|
| 将 Web 界面绑定到的主机。默认为“*”(所有接口) |
|
|
| 运行网络主机的端口 |
|
|
| 禁用 Web 界面,并立即开始测试。使用 -u 和 -t 来控制用户数量和运行时间 |
|
|
| 立即开始测试(不禁用 Web UI)。使用 -u 和 -t 来控制用户数量和运行时间 |
|
|
| 在运行完成 X 秒后完全退出 Locust。仅与–autostart 一起使用。默认是保持 Locust 运行,直到您使用 CTRL+C 将其关闭 |
|
|
| ==抑制== |
|
|
| 为 Web 界面启用基本身份验证。应按以下格式提供:用户名:密码 |
|
|
| 用于通过 HTTPS 提供服务的 TLS 证书的可选路径 |
|
|
| 用于通过 HTTPS 提供服务的 TLS 私钥的可选路径 |
|
|
| 设置 locust 以分布式模式运行,此进程作为主进程 |
|
|
| locust master 应该绑定的接口(主机名、ip)。仅在使用 –master 运行时使用。默认为 *(所有可用接口)。 |
|
|
| locust master 应该绑定的端口。仅在使用 –master 运行时使用。默认为 5557。 |
|
|
| 在开始测试之前,master 应该连接多少工人(仅当使用 –headless/autostart 时)。 |
|
|
| 在放弃之前,主人应该等待工人连接多长时间。默认永远等待 |
|
|
| 设置 locust 以分布式模式运行,此进程作为工作线程 |
|
|
| 用于分布式负载测试的locust master的主机或IP地址。仅在与 –worker 一起运行时使用。默认为 127.0.0.1。 |
|
|
| locust master 使用的连接端口用于分布式负载测试。仅在与 –worker 一起运行时使用。默认为 5557。 |
|
|
| 要包含在测试中的标签列表,因此只会执行具有任何匹配标签的任务 |
|
|
| 要从测试中排除的标签列表,因此只会执行没有匹配标签的任务 |
|
|
| 将当前请求统计信息以 CSV 格式存储到文件中。设置此选项将生成三个文件:[CSV_PREFIX]_stats.csv、[CSV_PREFIX]_stats_history.csv 和 [CSV_PREFIX]_failures.csv |
|
|
| 将每个统计条目以 CSV 格式存储到 _stats_history.csv 文件。您还必须指定“–csv”参数以启用此功能。 |
|
|
| 在控制台打印统计信息 |
|
|
| 只打印汇总统计信息 |
|
|
| 生成完成后重置统计信息。在分布式模式下运行时,应在 master 和 worker 上都设置 |
|
|
| 存储 HTML 报告文件 |
|
|
| 禁用 Locust 的日志记录设置。相反,配置由 Locust 测试或 Python 默认值提供。 |
|
|
| 在调试/信息/警告/错误/关键之间进行选择。默认为信息。 |
|
|
| 日志文件的路径。如果未设置,日志将转到 stderr |
|
|
| 设置当测试结果包含任何失败或错误时使用的进程退出代码 |
|
|
| 在退出之前等待模拟用户完成任何正在执行的任务的秒数。默认是立即终止。该参数只需要在运行 Locust 分布式时为 master 进程指定。 |
指定配置文件运行:
把命令行参数放到配置文件内, Locust 将默认查找~/.locust.conf
和./locust.conf
在项目目录下新建配置文件locust.conf
# locust.conf
locustfile = locust_files/my_locust_file.py
headless = true
master = true
expect-workers = 5
host = http://target-system
users = 100
spawn-rate = 10
run-time = 10m
# 指定配置文件运行
locust --config=locust.conf
分布式运行
# master 启动命令
locust -f my_locustfile.py --master
# slave 启动命令
locust -f my_locustfile.py --worker --master-host=[master host]
# 非web页面启动时,主节点等待子节点链接
locust -f my_locustfile.py --master --headless --expect-workers=x
更快的效能
Locust 附带了FastHttpUser它,它使用geventhttpclient代替。它提供了一个非常相似的 API,并且使用的 CPU 时间要少得多,有时可以将给定硬件上每秒的最大请求数增加 5 到 6 倍。
不可能说您的特定硬件可以处理什么,但在最好的情况下,使用 FastHttpUsers 的测试每个核心每秒可以处理接近 5000 个请求,而不是 HttpUser 大约 850 个请求(在 2018 年 MacBook Pro i7 上测试) 2.6GHz)
from locust import FastHttpUser, task, TaskSet
"""
与 HttpUser (python-requests) 相比,FastHttpUser 使用不同的 HTTP 客户端 (geventhttpclient)
FastHttpUser 它明显更快,但能力不强
"""
class HelloWorld(FastHttpUser):
@task
def hello(self):
self.client.get(path="http://www.rjcs.top", name="/")
if __name__ == '__main__':
import os
os.system("locust -f demo_locust_fast.py --headless -u 1 -r 1 -t 5s")