性能测试Locust--(10)延伸扩展及Locust API--0.14.4

Locust延伸扩展

Locust附带了很多事件,这些事件提供了以不同方式扩展Locust的钩子(hooks )。

事件监听器可以在模块级注册到Locust文件中。这里有一个例子:

from locust import events

def my_success_handler(request_type, name, response_time, response_length, **kw):
    print "Successfully fetched: %s" % (name)

events.request_success += my_success_handler

注意:
强烈建议你在侦听器中添加通配符关键字参数(上面代码中的** kw),以防止在以后的版本中添加新参数时代码崩溃。
要查看所有可用事件,请参阅事件[挂钩](https://docs.locust.io/en/stable/api.html#events)。

添加网络路由

Locust使用Flask来提供Web UI,因此很容易将Web端点添加到Web UI。只需将Flask应用程序导入您的locustfile并设置一条新路径:

from locust import web

@web.app.route("/added_page")
def my_added_page():
    return "Another page"

现在应该能够启动locust并浏览到:http://127.0.0.1:8089/added_page

Locust日志记录

Locust附带有基本的日志记录配置,该配置可以选择使用--loglevel和/或--logfile来修改配置。如果要控制日志记录配置,则可以提供--skip-log-setup标志,该标志将忽略其他参数。

Options选项

--skip-log-setup
禁用Locust的日志记录设置。相反,配置是由Locust test或Python默认设置提供配置。

--loglevel
在DEBUG/INFO/WARNING/ERROR/CRITICAL之间选择。默认值为INFO。简写为-L

--logfile
日志文件的路径。如果未设置,则日志将转到stdout / stderr。

Locust API

API的话以官网为准,以下是官网链接

API 官网链接

Locust 类

class Locust

表示一个策划并将要对系统进行负载测试的“用户”。
此用户的行为由**task_set**属性定义,该属性应该指向TaskSet类。
此类通常应由定义某种客户端的类继承。例如,在对HTTP系统进行负载测试时,您可能希望使用HttpLocust类。
task_set= None
TaskSet类,定义此Locust的执行行为

wait_time= None
该方法,返回执行Locust任务之间的时间(以秒为单位)。可以为单个TaskSet覆盖。
例如:

from locust import Locust, between
class User(Locust):
    wait_time = between(3, 25)

weight= 10
Locust被选中执行的概率。权重越高,被选中的机会越大。

HTTPLocust 类

class HttpLocust

表示一个策划并将要对系统进行负载测试的HTTP“用户”。
该HTTP用户的行为由**task_set**属性定义,该属性应该指向TaskSet类。
这个类在实例化时会创建一个 client 属性,这个属性的值是一个支持在请求间保持用户会话(user session)的 HTTP 客户端。

client=None
在 locust 实例化时创建的 HttpSession 实例。客户端支持 cookies,因此在 HTTP 请求间保持会话。

TaskSet类

class TaskSet(parent)

该类定义locust用户将要执行的一组任务。

当 TaskSet开始运行时,它将从 tasks 属性中选择一个任务并执行,然后调用这个任务的 wait_function 方法,之后再调用另一个任务,以此类推。
其中 wait_function 方法定义并返回一个以毫秒为单位的睡眠时间,wait_function 方法定义的睡眠时间的默认是介于 min_wait 和 max_wait 之间且均匀分布的随机数;然后它将调度另一个任务执行,等等。

TaskSets可以嵌套,这意味着一个 TaskSet 的 tasks 属性可以包含其他的 TaskSet。如果计划执行嵌套的 TaskSet ,则将实例化它并从当前执行的 TaskSet 进行调用。然后,当前运行的 TaskSet 中的执行将被移交给嵌套的 TaskSet ,嵌套的 TaskSet 将继续运行,直到遇到由 TaskSet.interrupt() 方法抛出的 InterruptTaskSet 异常时终止。(然后在第一个任务集中继续执行)。

client
引用根Locust实例的client属性。

interrupt(reschedule=True)
中断TaskSet并将执行控制移交给父TaskSet。

如果reschedule的值为True,父 locust 将立即重新调度并执行下一个任务。

这个方法不应该由根 TaskSet(即立即附加到 Locust 类的 task_set 属性)调用,而应该由层次结构中更深层次的嵌套 TaskSet 类调用。

locust= None
当TaskSet实例化后,会引用根Locust类实例。

parent= None
实例化TaskSet时,将引用父TaskSet或Locust类实例。对于嵌套TaskSet类很有用。

schedule_task(task_callable, args=None, kwargs=None, first=False)
将任务添加到Locust的任务执行队列中。
参数:

  • task_callable: 要调度的Locust任务计划表
  • args: 将传递给可调用任务(task_callable)的参数
  • kwargs: 关键字字典参数,将传递给可调用(task_callable)的任务.
  • first: 可选关键字参数。如果为 True,任务会被放到队列的首位。

tasks= []
列表中包含表示 locust 用户任务的可调用对象。

如果该参数值是一个列表,那么将从中随机挑选任务进行执行。

如果该参数值是一个元素为二元组 (callable, int) 的列表或元素为 callable: int 的字典,那么将随机选择要执行的任务,但是每个任务将根据其对应的 int 类型的值进行加权。所以在下面的例子中,ThreadPage 被选中的可能性是 write_post 的15倍:

class ForumPage(TaskSet):
    tasks = {ThreadPage:15, write_post:1}

wait_time()
该方法返回执行任务之间的时间(以秒为单位)。
例如:

from locust import TaskSet, between
class Tasks(TaskSet):
    wait_time = between(3, 25)
任务装饰器 task decorator

task(weight=1)
使用一个便捷装的饰器,以便能够为类中的TaskSet内联声明任务。

class ForumPage(TaskSet):
    @task(100)
    def read_thread(self):
        pass
    
    @task(7)
    def create_thread(self):
        pass
TaskSequence类(任务序列类)

classTaskSequence(parent)
定义 locust 用户将要执行的任务序列。

当 TaskSequence 开始执行时,它将从 tasks 属性值中根据任务的索引选择一个任务进行执行,然后调用它的定义了一个睡眠时间的 wait_fucntion 方法。wait_function 定义的睡眠时间默认为介于 min_wait 和 max_wait 之间且均匀分布的一个随机数,单位为毫秒。然后再调用索引为 index + 1 / % 的任务,以此类推。

TaskSequence 可以与 TaskSet 嵌套,这意味着 TaskSequence 的 tasks 属性可以包含 TaskSet 实例和其他TaskSequence 实例。如果计划执行嵌套的 TaskSet,则将实例化它并从当前执行的 TaskSet 调用它。然后,当前运行的 TaskSet 中的执行将被移交给嵌套的 TaskSet ,这个嵌套的 TaskSet 将继续运行,直到遇到由 TaskSet.interrupt()抛出 InterruptTaskSet异常时终止,然后在第一个 TaskSet 中继续执行。

在这个类中,任务应该被定义成一个列表,或者简单地由 @task_seq 装饰器定义。

client
引用根 Locust 实例的client属性。

interrupt(reschedule=True)
中断 TaskSet 并将执行控制权交给父 TaskSet。

如果 reschedule 的值为 True,父 locust 将立即重新调度并执行下一个任务。

这个方法不应该由根 TaskSet (即立即附加到 Locust 类的 task_set 属性)调用,而应该由层次结构中更深层次的嵌套 TaskSet 类调用。

schedule_task(task_callable, args=None, kwargs=None, first=False)
添加一个任务到Locust 的任务执行队列。
参数:

  • task_callable:要调度的 locust 任务。
  • args:要传递给 task_callable 的参数。
  • kwargs:要传递给 task_callable 的关键字参数的字典。
  • first:可选关键字参数。如果为 True,任务会被放到队列的首位。

wait_time()
该方法返回执行任务之间的时间(以秒为单位)。
例如:

from locust import TaskSet, between
class Tasks(TaskSet):
    wait_time = between(3, 25)
seq_task装饰器

seq_task(order)
用于在类中内联声明 TaskSequence 的任务。
例如:

class NormalUser(TaskSequence):
    @seq_task(1)
    def login_first(self):
        pass

    @seq_task(2)
    @task(25) # You can also set the weight in order to execute the task for `weight` times one after another.
    def then_read_thread(self):
        pass

    @seq_task(3)
    def then_logout(self):
        pass
HttpSession 类

between(min_wait, max_wait)
返回一个函数,该函数将在min_wait和max_wait之间返回一个随机数。
例如:

class User(Locust):
    # wait between 3.0 and 10.5 seconds after each task
    wait_time = between(3.0, 10.5)

constant(wait_time)
返回一个函数,该函数只返回wait_time参数指定的数字。
例如:

class User(Locust):
    wait_time = constant(3)

constant_pacing(wait_time)
返回一个函数,该函数将跟踪任务的运行时间,每次调用它时,它将返回一个等待时间,该等待时间将尝试使任务执行之间的总时间等于wait_time参数指定的时间。

在以下示例中,无论任务执行时间如何,任务总是每秒执行一次:

class User(Locust):
    wait_time = constant_pacing(1)
    class task_set(TaskSet):
        @task
        def my_task(self):
            time.sleep(random.random())

如果任务执行超过了指定的wait_time,则在开始下一个任务之前的等待时间为0。

HttpSession 类

**class HttpSession(base_url, *args, kwargs)
用于执行Web请求和在请求之间保留(会话)Cookie的类(以便能够登录和注销网站)。每个请求都被记录下来,以便Locust可以显示统计信息。

这是Python的 requests 库的requests.Session类的拓展,工作原理与是极其相似的。然而,发送请求的方法(get、post、delete、put、head、options、patch、request)现在可以接受一个 url 参数,这个参数只是 URL的路径部分,在这种情况下,URL的主机部分将取 HttpSession.base_url (继承自一个 Locust 类的 host 属性)的值。

发送请求的每个方法还接受两个额外的可选参数,这些参数是特定于 Locust ,在Python的 requests 库中不存在的:
参数:

  • name
    可选参数。可以指定为 Locust 的统计信息中的标签,用于代替 URL 路径。这可以用于将被请求的不同 URL 分组到 Locust 统计数据中的一个条目中。

  • catch_response
    可选参数。如果要设置,可以是一个布尔值。可以用来使请求返回为作为with 语句的参数的上下文管理器。这将允许根据响应内容将请求标记为失败,即使响应代码是 ok (2xx) ,反之亦然。可以使用 catch_response 捕捉请求,然后将其标记为成功,即使响应代码不是 ok (例如 500 或 404)。

__init__(base_url, \*args, \*\* kwargs)
x.init(…) 初始化x; see help(type(x)) for signature

delete(url, \*\*kwargs)
发送一个 DELETE 请求,返回一个 Response 对象。
参数:
url:新 Request 对象的URL。
**kwargs:request 的可选参数。
返回值类型:requests.Response 对象。

get(url, \*\*kwargs)
发送一个 GET 请求,返回一个 Response 对象。
参数:
url:新 Request 对象的URL。
**kwargs:request 的可选参数。
返回值类型:requests.Response 对象。

head(url, \*\*kwargs)
发送一个 HEAD 请求,返回一个 Response 对象。
参数:
url:新 Request 对象的URL。
**kwargs:request 的可选参数。
返回值类型:requests.Response 对象。

options(url, \*\*kwargs)
发送一个 OPTIONS 请求,返回一个 Response 对象。
参数:
url:新 Request 对象的URL。
**kwargs:request 的可选参数。
返回值类型:requests.Response 对象。

patch(url,data=None , \*\*kwargs)
发送一个 PATCH 请求,返回一个 Response 对象。
参数:
url:新 Request 对象的URL。
data:可选参数。发送到请求主体中的字典、bytes 或 file-like 对象。
**kwargs:request 的可选参数。
返回值类型:requests.Response 对象。

post(url,data=None , json=None, \*\*kwargs)
发送一个 POST 请求,返回一个 Response 对象。
参数:
url:新 Request 对象的URL。
data:可选参数。发送到请求主体中的字典、bytes 或 file-like 对象。
**kwargs:request 的可选参数。
json:可选参数。要发送到请求主体中的 json 格式数据。
返回值类型:requests.Response 对象。

put(url,data=None , \*\*kwargs)
发送一个 PUT 请求,返回一个 Response 对象。
参数
url:新 Request 对象的URL。
data:可选参数。发送到请求主体中的字典、bytes 或 file-like 对象。
**kwargs:request 的可选参数。
返回值类型:requests.Response 对象。

request(method, url, name=None , catch_response=False, **kwargs)
构造并发送一个requests.Request 。返回 requests.Response对象。

参数:
method:新 Request 对象的方法。
url:新 Request 对象的URL。
name:可选参数。
可以指定为 Locust 的统计信息中的标签,用于代替 URL 路径。这可以用于将被请求的不同 URL 分组到 Locust 统计数据中的一个条目中。
catch_response可选参数。如果要设置,可以是一个布尔值。可以用来使请求返回为作为with 语句的参数的上下文管理器。这将允许根据响应内容将请求标记为失败,即使响应代码是 ok (2xx) ,反之亦然。可以使用 catch_response捕捉请求,然后将其标记为成功,即使响应代码不是 ok (例如 500 或 404)。
params:可选参数。要发送到Request的查询字符串的字典或 bytes 对象。
data:可选参数。要发送到 Request主体中的字典或 bytes 对象。
headers:可选参数。与 Request一起发送的表示 HTTP headers 的字典。
cookies:可选参数。与 Request一起发送的表示 cookies 的 dict 或 CookieJar 对象。
files:可选参数。用于多部分编码上传的元素为 filename: filename: file-like-objects 的字典。
auth:可选参数:用于启用 Basic/Digest或自定义的 HTTP Auth 的元组或可调用对象。
timeout:可选参数。以浮点数或(连接超时、读取超时)元组的形式等待服务器发送数据的时间(以秒为单位)。
allow_redirects:可选参数。布尔类型。默认值为 True。 表示是否允许重定向。
proxies:可选参数。字典类型。键表示代理使用的协议,键值表示代理的URL。
stream:可选参数。是否立即下载响应内容。默认值为 False
verify:可选参数。如果为True,则会验证 SSL 证书。也可以提供一个 CA_BUNDLE 路径。
cert:可选参数。如果提供一个字符串。那么应该是指向SSL 客户端证书(.pem文件)的路径;如果是一个元组,则应该是 (‘cert’, ‘key’)。

Response类

这个类其实是位于python-requests库中的,但是由于 Locust在构造HTTP 请求的时候要用到这个类,并且在编写 Locust负载测试时,这个类也非常重要,所以就把这个类包含在了 API 文档里。您还可以查看请求文档中的Response类。

class Response
Response对象,它包含服务器对HTTP请求的响应。

apparent_encoding
明显的编码,由chardet库提供。

close()
用于释放链接。一旦调用此方法,就不能再次访问基础raw对象。
注意:通常不应该显式调用它。

content
响应的内容,以字节为单位。

cookies= None
服务器发回的一堆cookie。

elapsed= None
发送请求到响应到达之间的时间间隔(使用 timedelta 对象表示)。此属性专门度量从发送请求的第一个字节到完成对报头的解析所花费的时间。因此,它不受响应内容或 stream 关键字参数值的影响。

encoding= None
访问 r.text 时解码操作要用到的编码方式。

headers= None
不区分大小写的响应头字典。
例如,headers['content-encoding'] 将会返回响应头中键为 Content-Encoding 的键值。

history= None
请求历史记录中的响应对象列表。任何重定向响应都将在这里结束。该列表从最早的请求到最近的请求进行排序。

is_permanent_redirect
如果此响应是重定向的永久版本之一,则返回 True,否则返回 False。

is_redirect
如果此响应是可以自动处理的格式良好的HTTP重定向(通过 session.resolve_reredirect() 判断),则返回True,否则返回 False。

iter_content(chunk_size=1, decode_unicode=False)
迭代响应数据。当对请求设置stream=True时,这可以避免立即将内容读入内存以获得较大的响应。数据块大小是应该读入内存的字节数。这不一定是解码时返回的每个项的长度。
chunk_size的类型必须是int或None。None的值将根据流的值发挥不同的功能。
stream=True将在到达数据块时读取数据,无论块的大小如何。
如果stream=False,则以单个块的形式返回数据。

如果decode_unicode为True,那么将使用基于响应的最佳可用编码对内容进行解码。

iter_lines(chunk_size=512, decode_unicode=False, delimiter=None)
迭代响应数据,一次一行。当对请求设置stream=True时,这可以避免立即将内容读入内存以获得较大的响应。
注意:这种方法是不安全的。

json(**kwargs)
返回响应的 json 编码内容(如果有的话)。
**kwargs-- 表示要传给jason.loads函数的可选参数。
ValueError --如果响应的主体中不包含有效的 json 数据,则将引发 ValueError 异常。

links
返回已解析的响应头链接(如果有的话)。

next
返回一个PreparedRequest 对象,用于表示重定向链中的下一个请求(如果有的话)。

ok
如果 status_code 小于400,返回 True;如果不小于400,返回 False。

此属性检查响应的状态代码是否在400到600之间,以查看是否存在客户端错误或服务器错误。如果状态码在200到400之间,则返回 True ,而不是检查响应代码是否为 200 OK

raise_for_status()
如果发生HTTPError,则引发存储的HTTPError

reason= None
响应HTTP状态的文本原因.
例如: “Not Found” 或者 “OK”.

request= None
这是响应的PreparedRequest对象。

status_code= None
响应的HTTP状态的整数代码。
例如404或200。

text
使用Unicode字符表示的响应的内容。
如果 Response.encoding 是 None,则使用 chardet猜测编码。
响应内容的编码按照 RFC 2616 的规定,由 HTTP headers 唯一确定。如果可以利用非 HTTP 知识更好地猜测编码,应该在访问该特性之前为r.encoding设置合适的值。

url= None
响应的最终URL位置。

ResponseContextManager类

class ResponseContextManager(response)

可以充当上下文管理器的 Response 类,提供手动控制HTTP 请求在在 Locost 的统计数据中应该标记为成功还是失败的能力。

这个类是 Response 类的子类。包含两个额外的方法:successfailure

failure(exc)
将响应报告为失败。
其中参数 exc 可以是一个Python的异常类或者一个字符串。如果是一个字符串,那么将使用这个字符串来实例化 CatchResponseError 类。
例如:

with self.client.get("/", catch_response=True) as response:
    if response.content == b"":
        response.failure("No data")

success()
报告响应成功
例如:

with self.client.get("/does/not/exist", catch_response=True) as response:
    if response.status_code == 404:
        response.success()

InterruptTaskSet异常
exception InterruptTaskSet(reschedule=True)
在 Locust 任务内抛出这个异常时,将会中断这个 Locust 正在执行的当前任务。

事件钩子

事件钩子都是 locust.events.EventHook 类的实例。

class EventHook
简单事件类,用于为 locust 中不同类型的事件提供钩子。

下面的代码演示如何使用这个类:

my_event = EventHook()
def on_my_event(a, b, **kw):
    print "Event was fired with arguments: %s, %s" % (a, b)
my_event += on_my_event
my_event.fire(a="foo", b="bar")

如果 reverse 的值为 True,则处理程序将按照插入时的相反顺序运行。

注意: 强烈建议你在事件监听器中添加通配符关键字参数,以防止在以后的版本中添加新参数时代码中断。

可用的钩子

下面的事件钩子在 locust.events 模块下可用:
request_success= <locust.events.EventHook object>
当一个请求成功完成时触发。
监听者应该使用如下参数:

  • request_type:使用的请求方法。
  • name:被调用的URL的路径(如果在对客户端的调用中使用了名称,则重写名称)。
  • response_time:使用毫秒表示的响应时间。
  • response_length:响应的 Content-Length 值。

request_failure= <locust.events.EventHook object>
当一个请求失败时触发。
事件触发式将使用如下参数:

  • request_type:使用的请求方法。
  • name:被调用的URL的路径(如果在对客户端的调用中使用了名称,则重写名称)。
  • response_time:用毫秒表示的从发出请求到抛出异常时的时间间隔。
  • exception:抛出的异常的实例。

locust_error= <locust.events.EventHook object>
当 Locust 类的执行过程中出现异常时触发。
事件触发式将使用如下参数:

  • locust_instance:异常发生时的 Locust 类的实例。
  • exception:抛出的异常。
  • tb:回溯对象(从 sys.exc_info()[2] 得到)

report_to_master= <locust.events.EventHook object>
当 Locust 在 -slave 模式下运行时使用。用于将数据附加到定期发送给主服务器的数据字典上。当报告要发送到主服务器时,它会定期触发。

注意: Locust 使用的键 ‘stats’ 和 ‘errors’ 不应该被覆盖。

事件触发式将使用如下参数:

  • client_id:正在运行的 Locust 进程的客户端 ID。
  • data:可修改的数据字典,以便附加应发送到主服务器的数据。

slave_report= <locust.events.EventHook object>
当 locust 在 -master 模式下运行使用。并在 Locust 主服务器从从属服务器收到报告时触发。
此事件可用于聚合来自 Locust 从属服务器的数据。
事件触发式将使用如下参数:

  • client_id:报告 Locust 从属服务器的客户端 ID。
  • data:来自从属节点的数据字典。

hatch_complete= <locust.events.EventHook object>
当所有 locust 用户都已经生成时触发。
事件触发式将使用如下参数:

  • user_count:孵化出的用户数量。

quitting= <locust.events.EventHook object>
在退出 locust 进程时触发。

第三方工具

支持其他采样器协议,报告等。
Locust 插件

无需手动步骤即可自动执行分布式运行
Locust集群(蝗虫群)

使用其他语言
Locust主服务器和Locust从服务器通过交换msgpack消息进行通信,这是许多语言所支持的。因此,您可以使用任何喜欢的语言编写Locust任务。为了方便起见,一些库充当了从属运行程序。他们运行你的Locust任务,并定期向master报告。

Golang
Boomer

Java
Locust4j
Swarm

配置管理
部署Locust很容易,但是有些工具仍然可以提供一定程度的便利。

tinx.locust是Ansible的一个安装角色,用于配置和控制Locust系统服务,或使用ansible-container构建Locust docker映像。还管理locustfile和相应的测试数据。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软测小生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值