locust
Locust是什么?
Locust是一个易于使用、可编写脚本且可扩展的性能测试工具。
您可以使用常规Python代码定义用户的行为,而不是使用笨拙的UI或DSL。
这使Locust可以无限扩展,并且对开发人员非常友好。
特性
使用纯Python代码编写用户测试场景 如果希望用户循环执行某些条件行为或进行某些计算,则只需使用Python提供的常规编程结构即可。Locust在其自己的greenlet(轻量级 进程/协程)中运行每个用户。这使您能够像普通(阻塞)Python代码一样编写测试,
而不必使用回调或其他某种机制。
因为您的场景是 “只是 Python 代码”,所以您可以使用常规的IDE,并以常规代码的形式对测试进行控制(与其他一些使用XML或二进制格式的工具有所不同) 分布式&可伸缩——支持数十万用户 Locust使得运行分布在多台计算机上的负载测试变得容易。它是基于事件的(使用gevent),这使得单个进程可以处理数千并发用户。尽管可能还有其他工具可以在给定的硬件上每秒执行更多请求,
但是每个Locust用户的低开销使其非常适合测试高并发工作负载。 基于Web的UI Locust具有用户友好的Web界面,可实时显示测试进度。 您甚至可以在测试运行时更改负载。 Locust也可以在没有UI的情况下运行,从而使其易于用于CI / CD测试。 可以测试任何系统 尽管Locust是面向 站点/服务 的,但也可以用于测试几乎所有系统或协议。只需为您要测试的系统编写一个客户端,或者浏览社区创建的针对特定需求的客户端即可。 可拓展 Locust 非常小,非常灵活,我们打算使其一直保持这种特点。如果你想将报告数据发送到你喜欢的数据库&图形系统,请包装对REST API的调用以便处理系统的细节,或运行一个完全自定义的加载模式,那么你就可以无往不利。 命名和背景 Locust的诞生源于对现有解决方案的失望。 没有一个现有的负载测试工具能够很好地为动态网站生成真实的负载,在动态网站上,大多数页面会针对不同用户提供不同的内容。
现有工具使用笨拙的接口或冗长的配置文件来声明测试。在Locust中,我们采取了不同的方法。 您可以使用 Python 代码而不是配置格式或UI来定义用户的行为。 “Locust” 的这一名称来源于蝗虫物种,此种类以其成群的行为而闻名。 以前的Locust版本借用了自然界中的术语(群集、孵化,攻击等),但现在使用了更多的行业标准命名。
安装
安装 Python3.6+。
pip3 install locust
验证安装并显示版本号
locust -V
快速开始
在 Locust 中,可以使用 Python 代码定义用户行为。然后,您可以使用 locust
命令和(可选的)Web界面在收集请求统计信息时生成和模拟大量用户。
示例 locustfile.py
下面是一个简单的 locustfile.py 的例子
import time from locust import HttpUser, task, between class QuickstartUser(HttpUser): wait_time = between(1, 2.5) @task def hello_world(self): self.client.get("/hello") self.client.get("/world") @task(3) def view_items(self): for item_id in range(10): self.client.get(f"/item?id={item_id}", name="/item") time.sleep(1) def on_start(self): self.client.post("/login", json={"username":"foo", "password":"bar"})
让我们分开来看:
import time from locust import HttpUser, task, between
locust 文件只是一个可以从其他文件或包导入代码的普通 Python 模块。
class QuickstartUser(HttpUser):
在这里,我们为要模拟的用户定义了一个继承自 HttpUser 的类 QuickstartUser。在 HttpUser 类中,属性 client 是每一个模拟用户用来向我们要进行负载测试的目标系统发送 HTTP 请求的 HttpSession 的实例。当测试启动时,Locust 会为每一个模拟用户创建一个 QuickstartUser 类的实例,然后每一个这样的模拟用户将会在它们自己的 green gevent 线程中开始运行。
wait_time = between(1, 2.5)
QuickstartUser
类中定义了一个类属性 wait_time
,该属性会使得每一个模拟用户在每一个任务(下面由 @task
装饰器装饰的方法)执行之后等待 1~2.5 秒。更多细节,参见 [wait_time
属性](# wait_time 属性)
@task
def hello_world(self):
使用 @task
装饰器装饰的方法是 locust 文件的核心。Locust 会为每一个运行的用户创建一个调用这些方法的 greenlet(微线程)。
def hello_world(self): self.client.get("/hello") self.client.get("/world") @task(3) def view_items(self): ...
我们通过使用装饰器 @task 装饰 QuickstartUser 方法的方式添加了两个任务,其中一个任务具有较高的权重(3)。当 QuickstartUser 实例运行的时候,它会从声明的方法中选出一个(hello_world 或 view_items)并执行。任务的选取是随机的,但你可以给它们设置不同的权重。上面示例中的配置将会使得 view_items 被选中的几率是 hello_world 的 3 倍。当一个任务结束运行后后,该任务的所有者(模拟用户)会在等待时间(在上面的示例中,为 1~2.5 秒)内休眠。等待时间结束后,模拟用户会重选择一个任务,然后不断重复这个过程。
注意,只有被 @task 装饰的方法才会被选择,因此你可以以任何你喜欢的方式定义内部的帮助程序。
self.client.get("/hello")
self.client
属性使得模拟用户能够创建被 Locust 记录的 HTTP 调用。对于如何创建其他种类的请求、验证响应等,请参阅 使用 HTTP 客户端。
@task(3) def view_items(self): for item_id in range(10) self.client.get(f"/item?id={item_id}", name="/item") time.sleep(1)
在 view_items 任务中,我们使用可变的查询参数加载了 10 个不同的 URL。为了不在 Locust 的统计数据中创建 10 个单独的实体——因为统计数据是按照 URL 分组的——我们使用 name 参数 将所有的这 10 个请求分组到名为 "/item" 的单个实体中。
def on_start(self): self.client.post("/login", json={"username":"foo", "password":"bar"})
另外,我们还声明了一个 on_start
方法。每个模拟用户在启动时都会调用具有该名称的方法。 有关更多信息,请参见 on_start
和 on_stop
方法。
启动 Locust
将上述代码写入当前目录中名为 locustfile.py 的文件中,并运行:
locust
如果 Locust 文件位于其他位置,那么可以使用 -f
参数来指定:
locust -f locust_files/my_locust_file.py
参考连接
https://blog.csdn.net/swinfans/article/details/88915176 -- 官方文档翻译 https://www.cnblogs.com/liudinglong/ -- locust