Locust的学习笔记(二、如何编写locustfile)

这篇大部分就是对locust官网原文的翻译和总结了,例子的一部分也是拷的原文中的。英语好的就看看粗体部分就行了,粗体部分是我自己踩的坑,其他的尽可以去看原文
https://docs.locust.io/en/stable/writing-a-locustfile.html

Locustfile的5个类如下:

1.Userclass

一个用户类代表一类用户,每个实例代表一个被模拟的用户。可以定义一些公共属性。主要包括一下6种属性:
(1)wait_time attribute
不设置的话每个任务之间连续进行。分为
constant 在固定的时间内是常数
between 介于最小值和最大值之间的随机时间
constant_throughput用于确保任务每秒(最多)运行X次的自适应时间。
constant_tempo为自适应时间,确保任务(最多)每X秒运行一次(它是constant_throughput的数学倒数)。
(2)weight and fixed count attributes
weight 各任务之间的权重比
fixed count 固定执行次数
weight 、fixed count 和locust启动页面的Number of users一起考虑的时候会比较混乱。
在这里插入图片描述我直接说下结论吧。1.当Number of users大于等于程序中的各个user中的fixed count之和时,生成的用户数就是各user的fixed count。2. 当Number of users小于程序中的各个user中的fixed count之和时, fixed count基本等于weight,生成的用户比例基本是按照fixed count的比例生成的。
比如下面这段代码:

from locust import User, task, constant
import logging  as log
import datetime
import sre_constants

class TestUser1(User):
    fixed_count = 30
    wait_time = constant(5)
    @task
    def user1_task1(self):
        log.info("the user1 task1 complete!!!")
        log.info(datetime.datetime.now())
    @task
    def user1_task2(self):
        log.info("the user1 task2 complete!!!")
        log.info(datetime.datetime.now())

class TestUser2(User):
    fixed_count = 50
    wait_time = constant(10)
    @task
    def user2_task1(self):
        log.info("the user2 task1 complete!!!")
        log.info(datetime.datetime.now())
    @task
    def user2_task2(self):
        log.info("the user2 task2 complete!!!")
        log.info(datetime.datetime.now())

上面的例子中,fixed_count的和是30+50=80.
当启动数量为300的时候,启动数量就是80个。
在这里插入图片描述
当启动数量为26的时候。
在这里插入图片描述

(3)host attribute
等同于启动命令中的–host选项
(4)tasks attribute
定义在注解@task下
(5)environment attribute
暂时没想明白这个能干啥用,有用到的时候后续再补吧。
(6)on_start and on_stop methods
一个用户将在它开始运行时调用它的on_start方法,在它停止运行时调用它的on_stop方法。 对于TaskSet,当模拟用户开始执行该TaskSet时调用on_start方法,当模拟用户停止执行该TaskSet(当interrupt()被调用或用户被杀死时)时调用on_stop方法。

2.tasks

tasks有3种调用方法。
(1)最初的调用方法,@task注解,也是最常见的形式。与user的属性不同,task只能在括号中指定权重,而不能指定fixed_count,因为locust每次只从user中随机选择一个任务去执行。所以fixed_count没有意义。

from locust import User, task, between
	class MyUser(User):
    wait_time = between(5, 15)

    @task(3)
    def task1(self):
        pass

    @task(6)
    def task2(self):
        pass
        

(2)通过tasks属性调用。把任务集视为一个list。

from locust import User, constant
def my_task(user):
pass

class MyUser(User):
tasks = [my_task]
wait_time = constant(1)

与此同时,任务集也可以被视为一个字典,任务作为key,而调用的权重作为value
比如
{my_task: 3, another_task: 1}

my_task被调用3次,而其他任务只被调用1次。在内部,上面的字典实际上会被扩展成一个列表(任务属性也被更新了),
看起来像这样:
[my_task, my_task, my_task, another_task]
(3)tag注解,也就是标签。指定每个任务是哪个标签,

from locust import User, constant, task, tag

class MyUser(User):
wait_time = constant(1)

@tag('tag1')
@task
def task1(self):
    pass

@tag('tag1', 'tag2')
@task
def task2(self):
    pass

@tag('tag3')
@task
def task3(self):
    pass

@task
def task4(self):
    pass

然后在locust启动的时候通过–tags指定启动哪些标签,或者
–exclude-tags指定哪些标签不执行。

做一个最简单的实验,可以看出来locust每次确实是随机调用一个用户的一个task,用户的调用比例基本是按照权重来的就是1:1,任务就是随机的,调用次数可能会差一些。
代码如下,最简单的:

from locust import User, task
import logging  as log


class TestUser1(User):
    @task
    def user1_task1(self):
        log.info("the user1 task1 complete!!!")

    @task
    def user1_task2(self):
        log.info("the user1 task2 complete!!!")


class TestUser2(User):
    @task
    def user2_task1(self):
        log.info("the user2 task1 complete!!!")

    @task
    def user2_task2(self):
        log.info("the user2 task2 complete!!!")

生成用户的情况
在这里插入图片描述
任务执行结果如下所示:
user1task1:24603
user1task2:24161
user2task1:24357
user2task2:24389

3.events

简单的测试用不到这个内容,这个放到下一篇和钩子函数一起说。

4.httpuser以及其他的通讯协议。

(1)注意:由于python是可以引用其他包的,所以当使用其他通讯协议的时候可以直接引入其他协议的包,然后仍然调用
user和task两个类去建立压力测试的模板,把其他协议的代码放到@task下即可。例如下面这样。
import socket
from locust import User, TaskSet, task
import time
详细的讲解推荐https://www.cnblogs.com/jumping0709/p/15687877.html这篇。
(2)client attribute / HttpSession
包含所有的HTTP方法: get, post, put, …
具体的调用方式见
https://docs.locust.io/en/stable/api.html#locust.clients.HttpSession
(3)Validating responses
可以将返回置为失败,或者抛出一个异常。??这个后续还需要实验一下看看应用场景。

  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")

5.Tasksets

官方文档中注明此特性不常用。更建议在user中定义task,并且用循环和逻辑去进行控制。
taskset某些场景下还是有用的。比如我们模拟几种不同的用户习惯的时候,可以把每种用户习惯定义为一个tasksets。

asksets含有有序SequentialTaskSet class,并且可以使用tag属性。
并且一定要在最后调用self.interrupt()关闭进程。
官方给的例子如下所示:
from locust import User, TaskSet, constant
class ForumSection(TaskSet):
    wait_time = constant(1)

    @task(10)
    def view_thread(self):
        pass

    @task
    def create_thread(self):
        pass

    @task
    def stop(self):
        self.interrupt()

class LoggedInUser(User):
    wait_time = constant(5)
    tasks = {ForumSection:2}

    @task
    def my_task(self):
        pass

``

6.测试代码的结构

单个locust文件结构
common/
init.py
auth.py
config.py
locustfile.py
requirements.txt

当含有多个locust文件时,需要将多个locust文件放入一个单独的文件夹中。
common/
init.py
auth.py
config.py
my_locustfiles/
api.py
website.py
requirements.txt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值