test_start&test_stop
test_start:开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发
test_stop: 当负载测试停止时在每个节点上触发
@events.test_start.add_listener
def on_test_start(**kwargs):
print(f'A new test is starting')
@events.test_stop.add_listener
def on_test_stop(**kwargs):
print('A new test is ending')
init_command_line_parser
自定义locust命令行选项
# 使用实例:分布式压测时,如果场景需要不同worker对同一份测试数据中取的数据不同,
# 可自定义命令行选项,结合init事件使用
# ------------- 方式一 -------------------
@events.init_command_line_parser.add_listener
def add_user_parser(parser, **kwargs):
"""自定义locust命令参数"""
parser.add_argument(
"-fi",
"--first_index",
help="获取截取列表首索引"
"[fc:]",
default=0,
type=str
)
parser.add_argument(
"-li",
"--last_index",
help="获取截取列表末索引"
"[:li]",
default=0,
type=str
)
args = parser.parse_args()
if args.first_index:
os.environ['first_index'] = args.first_index
if args.last_index:
os.environ['last_index'] = args.last_index
# ----------- 方式二 ---------------------
@events.init_command_line_parser.add_listener
def add_user_parser(parser, **kwargs):
parser.add_argument("--user_id", type=str, default=None, required=True, help="召回用户ID")
parser.add_argument("--recall_type", type=str, default=None, required=True, help="召回类型")
parser.add_argument("--model_key", type=str, default=None, required=True, help="召回队列")
parser.add_argument("--scene", type=int, default=None, required=True, help="召回场景")
parser.add_argument("--content_type_limit", type=int, default=None, required=True, help="召回内容类型限定")
@events.init.add_listener
def _(environment, **kwargs):
logger.info(f"environment:{environment}")
logger.info(f"召回用户id~:{environment.parsed_options.user_id}")
logger.info(f"召回类型:{environment.parsed_options.recall_type}")
logger.info(f"召回队列:{environment.parsed_options.model_key}")
logger.info(f"召回场景:{environment.parsed_options.scene}")
logger.info(f"召回内容类型限定:{environment.parsed_options.content_type_limit}")
class RecallTask(TaskSet):
"""
# api perf
"""
def on_start(self):
"""
:return:
"""
logger.info(f"self: {self}")
logger.info(f"self.env: {self.user.environment}")
logger.info(f"self.env.parsed_options: {self.user.environment.parsed_options}")
logger.info(f"self.user.environment.__dict__: {self.user.environment.__dict__}")
# 自定义参数访问方式
self.user_id = self.user.environment.parsed_options.user_id
logger.info(f"self.user_id: {self.user_id}")
"""
使用方式一:
命令行输入:locust -f locustfile.py --web-host=0.0.0.0 -P 8876 --user_id tangyuehan --recall_type MeetingRecall --model_key Meeting --scene 63 --content_type_limit 9
使用方式二:
使用配置文件 master.conf
locustfile = _perf.py
logfile = _perf.log
loglevel = DEBUG
# headless = false
autostart = true
master = true
master-bind-host = 0.0.0.0
master-bind-port = 8879
expect-workers = 1
host =
users = 3
spawn-rate = 1
run-time = 10s
# csv = true
# csv-full-history = true
html = _locust.html
# 以下为自定义参数
user_id = xxxx
recall_type = xxx
model_key = xxx
scene = 63
content_type_limit = 9
"""
�init
每一个 Locust进程开始的时候触发init事件,可用于全局测试数据的初始化,也可针对每个worker进程设置。
# 结合上文的init_command_line_parser事件使用
@events.init.add_listener
def on_locust_init(environment, **kwargs):
print("当前环境变量first_index为: %s" % os.environ.get('first_index'))
print("当前环境变量last_index为: %s" % os.environ.get('last_index'))
for i in range(10000)[int(os.environ.get('first_index')): int(os.environ.get('last_index'))]:
ids.put_nowait(i)
print('初始化测试数据完毕')
if isinstance(environment.runner, MasterRunner):
print("master节点执行")
else:
print("worker节点执行")
�spawning_complete
当所有用户生成时触发,可用于集合点注册
all_locusts_spawned = BoundedSemaphore()
all_locusts_spawned.acquire()
@events.spawning_complete.add_listener
def on_hatch_complete(**kwargs):
all_locusts_spawned.release() # 创建集合点
�request_failure
�request_success
�request
请求完成时触发
自定义Locust客户端使用示例:
class SocketIO(object):
_locust_environment = None
start_time = 0
def __init__(self):
self.events = None
self.ws = None
def _require_failure(self, name, response_time, message, action, context, **kwargs):
"""统计失败请求数"""
self.events.request_failure.fire(
request_type="接收数据",
name=name,
response_time=response_time,
response_length=len(message),
exception=f'{action} Content Error!',
context=context,
)
def _require_success(self, name, response_time, message, **kwargs):
"""统计成功请求数"""
self.events.request_success.fire(
request_type="接收数据",
name=name,
response_time=response_time,
response_length=len(message),
)
def _require_fire(self, name, response_time, message, context, **kwargs):
"""通用统计请求数"""
self.events.request.fire(
request_type="接收数据",
name=name,
response_time=response_time,
response_length=len(message),
exception=None,
context=context,
)
.....
�
from locust import TaskSet, constant, task, events, FastHttpUser
from logzero import logger
from locust.runners import MasterRunner
from gevent._semaphore import BoundedSemaphore
"""hook事件"""
# 注册init初始化事件
@events.init.add_listener
def _(environment, **kwargs):
logger.info("***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***")
if not isinstance(environment.runner, MasterRunner):
logger.info("***slave test setup***")
else:
logger.info("***开始启动master节点***")
# 注册停止locust进程钩子事件
@events.quitting.add_listener
def _(environment, **kwargs):
logger.info("***Locust 进程退出时触发***")
# 注册test_start事件
@events.test_start.add_listener
def on_test_start(**kwargs):
logger.info("***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***")
# 注册test_stop事件
@events.test_stop.add_listener
def on_test_stop(**kwargs):
logger.info("***当负载测试停止时在每个节点上触发***")
# 创建集合点
all_locusts_spawned = BoundedSemaphore()
all_locusts_spawned.acquire()
# 注册集合点事件
@events.spawning_complete.add_listener
def on_hatch_complete(**kwargs):
all_locusts_spawned.release()
class DemoUser(FastHttpUser):
"""locust 任务"""
host = "http://coolaf.com"
max_wait = 0
min_wait = 0
def on_start(self):
"""setup
"""
logger.info("***每启动一个user执行一次***")
def on_stop(self):
"""teardown
"""
logger.info("***user停止后的清理工作***")
@task(1)
def execute_baidu_api(self):
"""压测接口"""
all_locusts_spawned.wait() # 限制在所有用户准备完成前处于等待状态
headers = {
"Connection": "keep-alive",
"Accept": "*/*"
}
with self.client.get(path="/zh/tool/unix", data=None, catch_response=True, headers=headers) as res:
if res.status_code == 200:
res.success()
else:
res.failure(f"{res.status_code}")
# if __name__ == "__main__":
# import os
# filename = os.path.abspath(__file__)
# os.system(f'locust -f {filename} --web-host=0.0.0.0 -P 8879')
"""
[I 211226 00:08:52 locustfile:18] ***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***
[I 211226 00:08:52 locustfile:20] ***slave test setup***
[2021-12-26 00:08:52,920] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting Locust 2.5.1
[2021-12-26 00:08:52,925] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting web interface at http://10.138.35.88:8090
[I 211226 00:08:52 locustfile:18] ***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***
[I 211226 00:08:52 locustfile:22] ***开始启动master节点***
[2021-12-26 00:08:52,943] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting Locust 2.5.1
[I 211226 00:08:52 locustfile:18] ***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***
[I 211226 00:08:52 locustfile:20] ***slave test setup***
[2021-12-26 00:08:52,945] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting Locust 2.5.1
[2021-12-26 00:08:52,953] liyanzhen-2020-001.novalocal/INFO/locust.runners: Client 'liyanzhen-2020-001.novalocal_44ae8e22fdf44c14aa41a083bf661dda' reported as ready. Currently 1 clients ready to swarm.
[2021-12-26 00:08:53,102] liyanzhen-2020-001.novalocal/INFO/locust.runners: Client 'liyanzhen-2020-001.novalocal_863954e80407496380e0f7e64e0d32c6' reported as ready. Currently 2 clients ready to swarm.
[2021-12-26 00:09:06,074] liyanzhen-2020-001.novalocal/INFO/locust.runners: Sending spawn jobs of 4 users at 1.00 spawn rate to 2 ready clients
[I 211226 00:09:06 locustfile:32] ***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***
[I 211226 00:09:06 locustfile:32] ***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***
[I 211226 00:09:06 locustfile:50] ***每启动一个user执行一次***
[I 211226 00:09:06 locustfile:32] ***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***
[I 211226 00:09:07 locustfile:50] ***每启动一个user执行一次***
[I 211226 00:09:08 locustfile:50] ***每启动一个user执行一次***
[I 211226 00:09:09 locustfile:50] ***每启动一个user执行一次***
[2021-12-26 00:09:09,171] liyanzhen-2020-001.novalocal/INFO/locust.runners: All users spawned: {"DemoUser": 4} (4 total users)
[I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
[I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
[I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
[I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
[I 211226 00:09:15 locustfile:38] ***当负载测试停止时在每个节点上触发***
[I 211226 00:09:15 locustfile:38] ***当负载测试停止时在每个节点上触发***
[2021-12-26 00:09:15,735] liyanzhen-2020-001.novalocal/INFO/locust.runners: Removing liyanzhen-2020-001.novalocal_44ae8e22fdf44c14aa41a083bf661dda client from running clients
[2021-12-26 00:09:15,736] liyanzhen-2020-001.novalocal/INFO/locust.runners: Client 'liyanzhen-2020-001.novalocal_44ae8e22fdf44c14aa41a083bf661dda' reported as ready. Currently 2 clients ready to swarm.
[2021-12-26 00:09:15,736] liyanzhen-2020-001.novalocal/INFO/locust.runners: Removing liyanzhen-2020-001.novalocal_863954e80407496380e0f7e64e0d32c6 client from running clients
[2021-12-26 00:09:15,736] liyanzhen-2020-001.novalocal/INFO/locust.runners: Client 'liyanzhen-2020-001.novalocal_863954e80407496380e0f7e64e0d32c6' reported as ready. Currently 2 clients ready to swarm.
[I 211226 00:09:16 locustfile:38] ***当负载测试停止时在每个节点上触发***
"""