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")
浙公网安备 33010602011771号