test_start&test_stop

test_start:开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发
test_stop: 当负载测试停止时在每个节点上触发

  1. @events.test_start.add_listener
  2. def on_test_start(**kwargs):
  3. print(f'A new test is starting')
  4. @events.test_stop.add_listener
  5. def on_test_stop(**kwargs):
  6. print('A new test is ending')

init_command_line_parser

自定义locust命令行选项

  1. # 使用实例:分布式压测时,如果场景需要不同worker对同一份测试数据中取的数据不同,
  2. # 可自定义命令行选项,结合init事件使用
  3. # ------------- 方式一 -------------------
  4. @events.init_command_line_parser.add_listener
  5. def add_user_parser(parser, **kwargs):
  6. """自定义locust命令参数"""
  7. parser.add_argument(
  8. "-fi",
  9. "--first_index",
  10. help="获取截取列表首索引"
  11. "[fc:]",
  12. default=0,
  13. type=str
  14. )
  15. parser.add_argument(
  16. "-li",
  17. "--last_index",
  18. help="获取截取列表末索引"
  19. "[:li]",
  20. default=0,
  21. type=str
  22. )
  23. args = parser.parse_args()
  24. if args.first_index:
  25. os.environ['first_index'] = args.first_index
  26. if args.last_index:
  27. os.environ['last_index'] = args.last_index
  28. # ----------- 方式二 ---------------------
  29. @events.init_command_line_parser.add_listener
  30. def add_user_parser(parser, **kwargs):
  31. parser.add_argument("--user_id", type=str, default=None, required=True, help="召回用户ID")
  32. parser.add_argument("--recall_type", type=str, default=None, required=True, help="召回类型")
  33. parser.add_argument("--model_key", type=str, default=None, required=True, help="召回队列")
  34. parser.add_argument("--scene", type=int, default=None, required=True, help="召回场景")
  35. parser.add_argument("--content_type_limit", type=int, default=None, required=True, help="召回内容类型限定")
  36. @events.init.add_listener
  37. def _(environment, **kwargs):
  38. logger.info(f"environment:{environment}")
  39. logger.info(f"召回用户id~:{environment.parsed_options.user_id}")
  40. logger.info(f"召回类型:{environment.parsed_options.recall_type}")
  41. logger.info(f"召回队列:{environment.parsed_options.model_key}")
  42. logger.info(f"召回场景:{environment.parsed_options.scene}")
  43. logger.info(f"召回内容类型限定:{environment.parsed_options.content_type_limit}")
  44. class RecallTask(TaskSet):
  45. """
  46. # api perf
  47. """
  48. def on_start(self):
  49. """
  50. :return:
  51. """
  52. logger.info(f"self: {self}")
  53. logger.info(f"self.env: {self.user.environment}")
  54. logger.info(f"self.env.parsed_options: {self.user.environment.parsed_options}")
  55. logger.info(f"self.user.environment.__dict__: {self.user.environment.__dict__}")
  56. # 自定义参数访问方式
  57. self.user_id = self.user.environment.parsed_options.user_id
  58. logger.info(f"self.user_id: {self.user_id}")
  59. """
  60. 使用方式一:
  61. 命令行输入: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
  62. 使用方式二:
  63. 使用配置文件 master.conf
  64. locustfile = _perf.py
  65. logfile = _perf.log
  66. loglevel = DEBUG
  67. # headless = false
  68. autostart = true
  69. master = true
  70. master-bind-host = 0.0.0.0
  71. master-bind-port = 8879
  72. expect-workers = 1
  73. host =
  74. users = 3
  75. spawn-rate = 1
  76. run-time = 10s
  77. # csv = true
  78. # csv-full-history = true
  79. html = _locust.html
  80. # 以下为自定义参数
  81. user_id = xxxx
  82. recall_type = xxx
  83. model_key = xxx
  84. scene = 63
  85. content_type_limit = 9
  86. """

�init

每一个 Locust进程开始的时候触发init事件,可用于全局测试数据的初始化,也可针对每个worker进程设置。

  1. # 结合上文的init_command_line_parser事件使用
  2. @events.init.add_listener
  3. def on_locust_init(environment, **kwargs):
  4. print("当前环境变量first_index为: %s" % os.environ.get('first_index'))
  5. print("当前环境变量last_index为: %s" % os.environ.get('last_index'))
  6. for i in range(10000)[int(os.environ.get('first_index')): int(os.environ.get('last_index'))]:
  7. ids.put_nowait(i)
  8. print('初始化测试数据完毕')
  9. if isinstance(environment.runner, MasterRunner):
  10. print("master节点执行")
  11. else:
  12. print("worker节点执行")

�spawning_complete

当所有用户生成时触发,可用于集合点注册

  1. all_locusts_spawned = BoundedSemaphore()
  2. all_locusts_spawned.acquire()
  3. @events.spawning_complete.add_listener
  4. def on_hatch_complete(**kwargs):
  5. all_locusts_spawned.release() # 创建集合点

�request_failure

请求完成且失败时触发

�request_success

请求完成且成功时触发

�request

请求完成时触发
自定义Locust客户端使用示例:

  1. class SocketIO(object):
  2. _locust_environment = None
  3. start_time = 0
  4. def __init__(self):
  5. self.events = None
  6. self.ws = None
  7. def _require_failure(self, name, response_time, message, action, context, **kwargs):
  8. """统计失败请求数"""
  9. self.events.request_failure.fire(
  10. request_type="接收数据",
  11. name=name,
  12. response_time=response_time,
  13. response_length=len(message),
  14. exception=f'{action} Content Error!',
  15. context=context,
  16. )
  17. def _require_success(self, name, response_time, message, **kwargs):
  18. """统计成功请求数"""
  19. self.events.request_success.fire(
  20. request_type="接收数据",
  21. name=name,
  22. response_time=response_time,
  23. response_length=len(message),
  24. )
  25. def _require_fire(self, name, response_time, message, context, **kwargs):
  26. """通用统计请求数"""
  27. self.events.request.fire(
  28. request_type="接收数据",
  29. name=name,
  30. response_time=response_time,
  31. response_length=len(message),
  32. exception=None,
  33. context=context,
  34. )
  35. .....

  1. from locust import TaskSet, constant, task, events, FastHttpUser
  2. from logzero import logger
  3. from locust.runners import MasterRunner
  4. from gevent._semaphore import BoundedSemaphore
  5. """hook事件"""
  6. # 注册init初始化事件
  7. @events.init.add_listener
  8. def _(environment, **kwargs):
  9. logger.info("***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***")
  10. if not isinstance(environment.runner, MasterRunner):
  11. logger.info("***slave test setup***")
  12. else:
  13. logger.info("***开始启动master节点***")
  14. # 注册停止locust进程钩子事件
  15. @events.quitting.add_listener
  16. def _(environment, **kwargs):
  17. logger.info("***Locust 进程退出时触发***")
  18. # 注册test_start事件
  19. @events.test_start.add_listener
  20. def on_test_start(**kwargs):
  21. logger.info("***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***")
  22. # 注册test_stop事件
  23. @events.test_stop.add_listener
  24. def on_test_stop(**kwargs):
  25. logger.info("***当负载测试停止时在每个节点上触发***")
  26. # 创建集合点
  27. all_locusts_spawned = BoundedSemaphore()
  28. all_locusts_spawned.acquire()
  29. # 注册集合点事件
  30. @events.spawning_complete.add_listener
  31. def on_hatch_complete(**kwargs):
  32. all_locusts_spawned.release()
  33. class DemoUser(FastHttpUser):
  34. """locust 任务"""
  35. host = "http://coolaf.com"
  36. max_wait = 0
  37. min_wait = 0
  38. def on_start(self):
  39. """setup
  40. """
  41. logger.info("***每启动一个user执行一次***")
  42. def on_stop(self):
  43. """teardown
  44. """
  45. logger.info("***user停止后的清理工作***")
  46. @task(1)
  47. def execute_baidu_api(self):
  48. """压测接口"""
  49. all_locusts_spawned.wait() # 限制在所有用户准备完成前处于等待状态
  50. headers = {
  51. "Connection": "keep-alive",
  52. "Accept": "*/*"
  53. }
  54. with self.client.get(path="/zh/tool/unix", data=None, catch_response=True, headers=headers) as res:
  55. if res.status_code == 200:
  56. res.success()
  57. else:
  58. res.failure(f"{res.status_code}")
  59. # if __name__ == "__main__":
  60. # import os
  61. # filename = os.path.abspath(__file__)
  62. # os.system(f'locust -f {filename} --web-host=0.0.0.0 -P 8879')
  63. """
  64. [I 211226 00:08:52 locustfile:18] ***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***
  65. [I 211226 00:08:52 locustfile:20] ***slave test setup***
  66. [2021-12-26 00:08:52,920] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting Locust 2.5.1
  67. [2021-12-26 00:08:52,925] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting web interface at http://10.138.35.88:8090
  68. [I 211226 00:08:52 locustfile:18] ***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***
  69. [I 211226 00:08:52 locustfile:22] ***开始启动master节点***
  70. [2021-12-26 00:08:52,943] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting Locust 2.5.1
  71. [I 211226 00:08:52 locustfile:18] ***初始化 locust,发生在解析locust文件之后,但在测试接口开始之前,分布式执行则每个slave初始化一次***
  72. [I 211226 00:08:52 locustfile:20] ***slave test setup***
  73. [2021-12-26 00:08:52,945] liyanzhen-2020-001.novalocal/INFO/locust.main: Starting Locust 2.5.1
  74. [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.
  75. [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.
  76. [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
  77. [I 211226 00:09:06 locustfile:32] ***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***
  78. [I 211226 00:09:06 locustfile:32] ***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***
  79. [I 211226 00:09:06 locustfile:50] ***每启动一个user执行一次***
  80. [I 211226 00:09:06 locustfile:32] ***开始新的负载测试时在每个节点上触发。如果在测试期间用户数量发生变化,则不会再次触发***
  81. [I 211226 00:09:07 locustfile:50] ***每启动一个user执行一次***
  82. [I 211226 00:09:08 locustfile:50] ***每启动一个user执行一次***
  83. [I 211226 00:09:09 locustfile:50] ***每启动一个user执行一次***
  84. [2021-12-26 00:09:09,171] liyanzhen-2020-001.novalocal/INFO/locust.runners: All users spawned: {"DemoUser": 4} (4 total users)
  85. [I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
  86. [I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
  87. [I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
  88. [I 211226 00:09:15 locustfile:55] ***user停止后的清理工作***
  89. [I 211226 00:09:15 locustfile:38] ***当负载测试停止时在每个节点上触发***
  90. [I 211226 00:09:15 locustfile:38] ***当负载测试停止时在每个节点上触发***
  91. [2021-12-26 00:09:15,735] liyanzhen-2020-001.novalocal/INFO/locust.runners: Removing liyanzhen-2020-001.novalocal_44ae8e22fdf44c14aa41a083bf661dda client from running clients
  92. [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.
  93. [2021-12-26 00:09:15,736] liyanzhen-2020-001.novalocal/INFO/locust.runners: Removing liyanzhen-2020-001.novalocal_863954e80407496380e0f7e64e0d32c6 client from running clients
  94. [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.
  95. [I 211226 00:09:16 locustfile:38] ***当负载测试停止时在每个节点上触发***
  96. """