Locust 2.8 瞬时并发处理 task 级别的瞬时并发 分布式运行时,针对多个worker的处理

task 级别的瞬时并发

针对 task 级别的瞬时并发,locust 本身并没有给出解决方案

话不多说帖代码:

from requests.packages.urllib3.exceptions import InsecureRequestWarning

from locust import task, SequentialTaskSet, between, FastHttpUser

from common.prometheus_exporter import *

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# SequentialTaskSet 按顺序执行的 Set
class MomentStart(SequentialTaskSet):
    user_item = None

    @task
    def exams_user_checkExamCondition(self):

        with self.client.post("/api1") as res:
            assert res.status_code == 200

            """ 瞬时并发队列处理 """
            # my_queue out_queue 已经在 test_start 阶段被初始化
            if not self.user.environment.my_queue.empty() and self.user.environment.out_queue.empty():
                # 消费一个my_queue
                num = self.user.environment.my_queue.get()
                # 阻塞线程
                self.user.environment.my_queue.task_done()
                
                if self.user.environment.my_queue.empty():
                    pass
                else:
                    # my_queue全部消费完之后,才结束阻塞
                    self.user.environment.my_queue.join()
                # 生产一个out_queue
                self.user.environment.out_queue.put(num)

    @task
    def exams_getExamLeaveInfo(self):

        with self.client.get("/api2") as res:
            assert res.status_code == 200

            """ 瞬时并发队列处理 """
            if not self.user.environment.out_queue.empty():
                # 生产一个my_queue 供下一次循环使用
                self.user.environment.my_queue.put(self.user.environment.out_queue.get())
                self.user.environment.out_queue.task_done()



class TestUser(FastHttpUser):
    wait_time = between(0.5, 1)

    tasks = [MomentStart]

分布式时如何处理瞬时并发

在分布式运行的时候,你会发现这个方法失效了,即使你的用户都已经准备完成了,但是并没有进行并发

因为每个 worker 都是 均匀分配运行用户数 的,比如指定了100个用户,启动了2个 worker ,那么每个worker的用户数应该是50,所以需要在 test_start 做初始化,,把并发用户数均匀的分配给每一个 worker

下面这个示例,结合上面的队列处理,就能够解决这个问题,并且可以在WEB UI 中灵活的分配你的并发

# 持续时间
@events.init_command_line_parser.add_listener
def _(parser):
    parser.add_argument("--duration-time", include_in_web_ui=True, type=int, env_var="LOCUST_DURATION_TIME", default=300, help="持续时间")

# 用户数量
@events.init_command_line_parser.add_listener
def _(parser):
    parser.add_argument("--users-count", include_in_web_ui=True, type=int, env_var="LOCUST_USERS_COUNT", default=100, help="用户数量")

# 每秒孵化用户数
@events.init_command_line_parser.add_listener
def _(parser):
    parser.add_argument("--spawn-rate-count", include_in_web_ui=True, type=int, env_var="LOCUST_SPAWN_RATE_COUNT", default=1, help="每秒加载用户数")


# 负载机数量
@events.init_command_line_parser.add_listener
def _(parser: LocustArgumentParser):
    parser.add_argument("--worker-count", include_in_web_ui=True, type=int, env_var="LOCUST_WORKER_USER", default=1, help="负载机数量")



# 打印环境日志
@events.test_start.add_listener
def _(environment, **kw):
    print(f"Custom argument supplied duration-time: {environment.parsed_options.duration_time}")
    print(f"Custom argument supplied users-count: {environment.parsed_options.users_count}")
    print(f"Custom argument supplied spawn-rate-count: {environment.parsed_options.spawn_rate_count}")



"""
	对队列的处理
	!!!结合上面的瞬时并发处理一起使用!!!
""" 

@events.test_start.add_listener
def on_locust_init(environment, **kwargs):
    # 每个worker的并发用户数 = 总的用户数 / worker总数
    concurrence_user = int(environment.parsed_options.users_count / environment.parsed_options.worker_count)
    logging.info(f'users_count: {environment.parsed_options.users_count}, concurrence_user: {concurrence_user}, worker_count: {environment.parsed_options.worker_count}')
    environment.out_queue = queue.Queue(concurrence_user)
    environment.my_queue = queue.Queue(concurrence_user)
    # 然后填充队列
    for i in range(concurrence_user):
        environment.my_queue.put(i)



# 自定义负载时长、负载用户数、用户加载数量
class StagesShape(LoadTestShape):

    def stages_details(self):
        stages = [
            {"duration": self.runner.environment.parsed_options.duration_time,
             "users": self.runner.environment.parsed_options.users_count,
             "spawn_rate": self.runner.environment.parsed_options.spawn_rate_count},
        ]
        return stages

    def tick(self):
        run_time = self.get_run_time()

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

        return None
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值