• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
九五二七乌托邦
博客园    首页    新随笔    联系   管理    订阅  订阅

3.locust实例

一、events常用用法
# *_*coding:utf-8 *_*
# @Author : zyb
from locust import TaskSet, task, FastHttpUser, between, events
# 定义任务集类
@events.request.add_listener
def on_request(request_type, name, context, response, exception, **kwargs):
    if request_type == "GET" and name == "测试":
        print('判断执行')
@events.test_start.add_listener
def get_test_start( **kwargs):
    print('这个函数整个压测只执行一次')

@events.test_stop.add_listener
def aa(**kwargs):
    print('测试时,点击stop后执行的程序,和test_stopping差别不大')

class AAA(TaskSet):
    @task
    def task_get(self):
        url = '/GetTztAll/'
        self.client.get(url=url, name='测试')
    @task
    def task_post(self):
        url = '/GetTztAll/'
        self.client.post(url=url, name='测试')
# 定义用户类
class WebsiteUser(FastHttpUser):
    tasks = [AAA]
    wait_time = between(1, 2)
if __name__ == "__main__":
    import os
    file_path = os.path.abspath(__file__)
    os.system(f"locust -f {file_path} --host=http://127.0.0.1:8000")

二、执行参数例子

# *_*coding:utf-8 *_*
# @Author : zyb
# HttpUser :保持会话。FastHttpUser:高性能
from locust import TaskSet, task, HttpUser,FastHttpUser, between, constant_throughput, constant_pacing, constant
#argument_parser 这个可以修改执行参数的
from gevent._semaphore import Semaphore
all_locust_spawend = Semaphore()
all_locust_spawend.acquire()
#@seq_task(2)顺序执行,1-->10  1先执行
#依赖调用首要执行的函数执行后调用下面的方法
#self.schedule_task('依赖的task')
#定义任务集类
class proBehavior(TaskSet):
    def on_start(self):
        #添加集合点、登录等场景,只执行一次
        print('pro登录开始')
        # all_locust_spawend.wait(20)
    @task
    def my_task_one(self):
        url = '/pro/'
        #catch_response=True,允许请求标记为失败
        with self.client.get(url=url,name='pro采购信息', verify=False,timeout=10,catch_response=True) as response:
            if response.status_code==200:
                response.success()
            else:
                response.failure("Failed!")

    @task
    def my_task_two(self):
        url = '/users/'
        # catch_response=True,允许请求标记为失败
        with self.client.get(url=url, name='pro获取用户', verify=False, timeout=10, catch_response=True) as response:
            if response.status_code == 200:
                response.success()
            else:
                response.failure("Failed!")
    def on_stop(self):
        print('pro结束后每个用户执行一次')

#定义用户类
class WebsiteUser(FastHttpUser):
    tasks = [proBehavior]
    wait_time = between(1, 5)
    # 恒定吞吐量无论任务执行时间如何,任务将始终每10秒执行一次:
    # wait_time = constant_throughput(0.1)
if __name__ == "__main__":
    import os
    file_path = os.path.abspath(__file__)
    os.system(f"locust -f {file_path} --host=http://127.0.0.1:8000")
    os.system(f"locust -f --host=http://127.0.0.1:8000 --no-web -c 1000 -r 100 --run-time 1h30m --stop-timeout 99")

    #分布式
    #主机: --mastert
    #执行机: --slave --mastert-host=主机ip地址

    #命令行执行参数:
    #   -f xxx.py:执行文件
    #   --host=https://www.xx.com :执行域名
    #   --web-host=0.0.0.0 :web界面的域名
    #   --no-web:不使用web界面
    #   -c:用户数
    #   -r:每秒孵化率(每秒启动数)
    #   --expect-slaves:执行机数量
    #   --run-time:运行时间:(h:小时,m:分钟,s:秒)
    #   --csv=:保存执行结果

三、触发时机的函数

from locust.runners import (MasterRunner, WorkerRunner, STATE_STOPPING, STATE_STOPPED,
                            STATE_CLEANUP, LocalRunner)
from locust import HttpUser, TaskSet, task, events, LoadTestShape, run_single_user
from gevent._semaphore import Semaphore
import json
import traceback
import gevent
import time

'''请求成功时触发'''
def on_request_success(request_type, name, response_time, response_length):
    print( 'success  Type: {}, Name: {}, Time: {}ms, length: {}'
           .format(request_type, name, response_time,response_length))

'''请求失败时触发'''
def on_request_failure(request_type, name, response_time, response_length, exception):
    print('failure  Type: {}, Name: {}, Time: {}ms, exception: {}, response_length:{}'
          .format(request_type, name, response_time, exception, response_length))

'''在执行locust类内发生异常时触发'''
def on_locust_error(locust_instance, exception, tb):
    print("error  locust_instance: {}, exception: {}, traceback: {}"
          .format(locust_instance, exception, traceback.format_tb(tb)))

'''退出进程时回调'''
def on_quitting(environment, **kwargs):
    print("Test quit")

'''停止测试的时候客户端会调这个方法发送数据到主节点这边'''
def on_test_stop(environment, **kwargs):
    if not isinstance(environment.runner, MasterRunner):
        print("Cleaning up test data")
        # 节点往主节点发送的数据
        environment.runner.send_message('acknowledge_users', f"Thanks for the Cleaning up test data users!")
    else:
        users = [
            {"name": "User1"},
            {"name": "User2"},
            {"name": "User3"},
        ]
        environment.runner.send_message('test_users', users)

'''#定义worker节点注册的消息'''
def setup_test_users(environment, msg, **kwargs):
    for user in msg.data:
        print(f"User {user['name']} received")
    environment.runner.send_message('acknowledge_users', f"Thanks for the {len(msg.data)} users!")

'''定义matser节点注册的消息'''
def on_acknowledge(msg, **kwargs):
    print("recv worker data :{}".format(msg.data))

'''
#主动退出进程时:environment.process_exit_code = 0
#判断错误率大于多少N主动退出进程
#判断响应时间大于多少N主动退出进程
#判断响应时间
'''
def checker(environment):
    while not environment.runner.state in [STATE_STOPPING, STATE_STOPPED, STATE_CLEANUP]:
        time.sleep(1)
        if environment.stats.total.fail_ratio > 0.01:
            print("Test failed due to failure ratio > 1%,code=1")
            environment.process_exit_code = 1
            '''这个语句是退出'''
            environment.runner.quit()
        elif environment.stats.total.avg_response_time > 200:
            print("Test failed due to average response time ratio > 200 ms,code=1")
            environment.process_exit_code = 1
        elif environment.stats.total.get_response_time_percentile(0.95) > 300:
            print("Test failed due to 95th percentile response time > 800 ms,code=1")
            environment.process_exit_code = 1
        else:
            environment.process_exit_code = 0
            pass
            # print("Test Normal task exit code=0")


'''
#初始化时绑定的重写方法,该类中进行了worler和master节点的消息注册
'''
def on_locust_init(environment, **kwargs):
    if not isinstance(environment.runner, MasterRunner):
        '''
        #初始化的时候注册消息,客户端的消息,往客户端的往这个类型发就行
        '''
        environment.runner.register_message('test_users', setup_test_users)
    if not isinstance(environment.runner, WorkerRunner):
        '''
        #初始化的时候注册消息,服务端的消息,往后服务端往这个类型发就行
        '''
        environment.runner.register_message('acknowledge_users', on_acknowledge)

    if isinstance(environment.runner, MasterRunner) or isinstance(environment.runner, LocalRunner):
        gevent.spawn(checker, environment)


def on_test_start(environment, **kwargs):
    '''如果运行环境不是主节点'''
    if not isinstance(environment.runner, MasterRunner):
        users = [
            {"name": "User1"},
            {"name": "User2"},
            {"name": "User3"},
        ]
        environment.runner.send_message('test_users', users)


'''''''''
#创建集合点,当locust实例产生完成时触发
'''
all_locusts_spawned = Semaphore()
# 上锁
all_locusts_spawned.acquire()
'''
#生成所有locust用户时触发
'''
def on_hatch_complete(**kwargs):
    # 释放锁
    all_locusts_spawned.release()
'''
#事件回调绑定
'''
events.spawning_complete.add_listener(on_hatch_complete)
events.request_success.add_listener(on_request_success)
events.request_failure.add_listener(on_request_failure)
events.user_error.add_listener(on_locust_error)
events.quitting.add_listener(on_quitting)
events.init.add_listener(on_locust_init)
'''
#主节点才触发
'''
events.test_start.add_listener(on_test_start)
events.test_stop.add_listener(on_test_stop)
header = {"Content-Type": "application/json;charset=UTF-8"}

四、队列参数使用

# *_*coding:utf-8 *_*
# @Author : zyb
import queue
# q = queue.SimpleQueue() #不限制大小,仅仅支持添加数据和取数据,先进先出。
q = queue.Queue()   # 可以设置大小用maxsize参数。先进先出。如管道。添加数据 q.put("item1")。取数据 q.get()
# q = queue.LifoQueue() # LIFO 队列,也称为栈,特点后进先出,如桶。添加数据 q.put("item1")。取数据 q.get()
# q = queue.PriorityQueue() #优先级队列。按照优先级数字出。添加数据  q.put((3, "item3"))。取数据 q.get(),数字小最优先。
q.qsize() #返回队列的大小
q.empty() #队列为空,返回 True,否则返回 False
q.full() #队列满返回 True,否则返回 False

五、单次并发

# 单次并发
from locust import HttpUser, task, between
from gevent.event import Event
rendezvous_event = Event()
user_count = 0
import time

class MyUser(HttpUser):
    wait_time = between(1, 3)

    # def on_start(self):
    #     self.user_id = id(self)  # 初始化唯一标识
    @task
    def single_request(self):
        global user_count
        user_count += 1
        if user_count >= 30:
            rendezvous_event.set()
        rendezvous_event.wait()
        if not hasattr(self, "request_done"):  # 确保每个用户只请求一次
            # print(f"User {self.user_id} sending request at {time.time()}")
            self.client.get("/")
            self.request_done = True

if __name__ == "__main__":
    import os
    file_path = os.path.abspath(__file__)
    os.system(f"locust -f {file_path} --host=https://www.baidu.com" )

六、阶梯加压

# *_*coding:utf-8 *_*
# @Author : zyb
from locust import HttpUser, TaskSet, task, constant,FastHttpUser
from locust import LoadTestShape
class UserTasks(TaskSet):
    @task
    def get_root(self):
        self.client.get("/GetTztAll/")
class WebsiteUser(FastHttpUser):
    wait_time = constant(0.5)
    tasks = [UserTasks]
class StagesShape(LoadTestShape):
    #duration:运行时间,注意的地方就是 他是总时间,不是固定。
    #users:用户数
    #spawn_rate:每秒孵化数
    stages = [
        {"duration": 30, "users": 10, "spawn_rate": 10},
        {"duration": 80, "users": 50, "spawn_rate": 10},
    ]
    def tick(self):
        run_time = self.get_run_time()

        for stage in self.stages:
            if run_time < stage["duration"]:
                tick_data = (stage["users"], stage["spawn_rate"])
                return tick_data
        return None

if __name__ == "__main__":
    import os
    file_path = os.path.abspath(__file__)
    os.system(f"locust -f {file_path} --host=http://127.0.0.1:8000")

七、顺序加压

# *_*coding:utf-8 *_*
# @Author : zyb
import queue
q = queue.Queue()
for i in range(100):
    q.put(i)
from locust import FastHttpUser, task, between, SequentialTaskSet
class MySequentialTasks(SequentialTaskSet):
    @task
    def task_one(self):
        global ii
        ii = q.get()
        self.client.get("/LocustTest/",name='get')
        print('get',ii)
    @task
    def task_two(self):
        self.client.post("/LocustTest/",name='post')
        print('post',ii)

class MySequentialUser(FastHttpUser):
    wait_time = between(1, 5)  # 用户之间等待的时间范围
    tasks = [MySequentialTasks]  # 指定顺序任务集
if __name__ == '__main__':
    import os
    file_path = os.path.abspath(__file__)
    os.system(f"locust -f {file_path} --host=http://127.0.0.1:8000")

 

posted @ 2025-12-19 11:19  九五二七乌托邦  阅读(6)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3