locust快速入门--使用分布式提高测试压力

背景:

使用默认的locust启动命令进行压测时,尽管已经将用户数设置大比较大(400),但是压测的时候RPS一直在100左右。需要增加压测的压力。

问题原因:

如果你是通过命令行启动的或者参考之前文章的启动方式:

  • 命令行:

  • locust 库方法:
    `

因为create_local_runner会创建一个LocalRunner,这个runner只有一个WorkerNode

解决方式:

  • 单机:充分利用CPU每一个核心

    • os_start(True),指定参数True``则充分利用cpu的性能,否则就和之前调用create_local_runner一样。 使用os、multiprocessing完成, 模拟的是命令行启动locust的操作.。
    • local_start(True),使用locust的库方法,根据CPU的核心数、线程数创建WorkerNode
  • 多机:利用多台机器的能力提高测试压力

    • slave_start(master_ip, master_port=5557),指定主机的IP及端口号。
    python 复制代码
    # -*- coding:UTF-8 -*-
    
    """
     @ProjectName  : pyExamples 
     @FileName     : locust_demo
     @Description  : 
     @Time         : 2024/1/4 下午11:30
     @Author       : Qredsun
     """
    import os
    import socket
    import psutil
    from multiprocessing import Process
    from locust import HttpUser, events, task, between
    from locust.env import Environment
    
    
    class UserRun(HttpUser):
        wait_time = between(min_wait=0.1, max_wait=0.2)  # 设置task运行间隔
    
        @task  # 装饰器,说明下面是一个任务
        def getuser_(self):
            url = 'https://analytics.cnblogs.com/api/v1/reports'  # 接口请求的URL地址
            payload = {"blogId": 485117, "postId": 10365033,
                       "url": "https://www.cnblogs.com/happyyangyanghappy/p/10365033.html", "resolution": "1920x1080",
                       "referrer": "https://www.ecosia.org/", "createdAt": "2024-01-04T16:17:52.241Z"}
            with  self.client.post(url, json=payload, catch_response=True) as rsp:
                if rsp.status_code == 200:
                    rsp.success()
                else:
                    rsp.failure(f'接口调用失败:{rsp.json()}')
    
    
    def current_ip():
        ip = None
        interfaces = psutil.net_connections(kind='inet4')
        for interface in interfaces:
            if interface.type == socket.SocketKind.SOCK_STREAM and interface.status is not None and bool(interface.raddr):
                if interface.raddr.ip != "127.0.0.1":
                    print(interface.laddr.ip)
                    ip = interface.laddr.ip
                break
        return ip
    
    
    def local_start(multiprocess=False, master_ip=None):
        # 使用locust库启动
        web_host = current_ip()
        web_port = 8089
    
        runners = []
    
        master_env = Environment(user_classes=[UserRun], events=events)
        if multiprocess:
            # 主节点
            master_ip = web_host
            master_port = 5557
            master_runner = master_env.create_master_runner(master_bind_host=master_ip, master_bind_port=master_port)
            # 工作节点数量
            process_num = psutil.cpu_count()
    
            # slave
            for _ in range(process_num):
                env = Environment(user_classes=[UserRun], events=events)
                slave_runner = env.create_worker_runner(master_host=master_ip, master_port=master_port)
                runners.append(slave_runner)
    
        else:
            master_runner = master_env.create_local_runner()
        runners.append(master_runner)
        web_ui = master_env.create_web_ui(host=web_host, port=web_port)
        runners.append(web_ui)
    
        master_env.events.init.fire(environment=master_env, runner=master_runner, web_ui=web_ui)
    
        for runner in runners:
            runner.greenlet.join()
    
    
    def os_start(multiprocess=False):
        # 使用os库启动
        web_host = current_ip()
        web_port = 8089
    
        master_ip = web_host
        master_port = 5557
    
        master_cmd = f"locust -f {os.path.basename(__file__)}  --web-host {web_host} --web-port {web_port} --run-time 180s"
    
        process_num = psutil.cpu_count(logical=True)
        process_list = []
        if multiprocess:
            if os.name == "nt":
                # Windows 系统
                master_cmd += f" --master --master-bind-host {master_ip} --master-bind-port {master_port}"
                process_list.append(Process(target=os.system, args=(master_cmd,)))
                slave_cmd = f"locust -f {os.path.basename(__file__)}  --worker --master-host {master_ip} --master-port {master_port}"
                for _ in range(process_num):
                    process_list.append(Process(target=os.system, args=(slave_cmd,)))
            else:
                # linux
                master_cmd += f" --master-host {master_ip} --master-port {master_port} --processes -1"
                process_list.append(Process(target=os.system, args=(master_cmd,)))
        else:
            process_list.append(Process(target=os.system, args=(master_cmd,)))
    
        for p in process_list:
            p.start()
    
        for p in process_list:
            p.join()
    
    def slave_start(master_ip, master_port=5557):
        # 使用locust库启动
        runners = []
        # 工作节点数量
        process_num = psutil.cpu_count()
    
        # slave
        for _ in range(process_num):
            env = Environment(user_classes=[UserRun], events=events)
            slave_runner = env.create_worker_runner(master_host=master_ip, master_port=master_port)
            runners.append(slave_runner)
    
        for runner in runners:
            runner.greenlet.join()
    
    if __name__ == '__main__':
        # os_start(True)
        local_start(True)

工作效果:


相关推荐
斯凯利.瑞恩2 分钟前
Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户附数据代码
python·决策树·随机森林
yannan2019031324 分钟前
【算法】(Python)动态规划
python·算法·动态规划
蒙娜丽宁34 分钟前
《Python OpenCV从菜鸟到高手》——零基础进阶,开启图像处理与计算机视觉的大门!
python·opencv·计算机视觉
光芒再现dev35 分钟前
已解决,部署GPTSoVITS报错‘AsyncRequest‘ object has no attribute ‘_json_response_data‘
运维·python·gpt·语言模型·自然语言处理
好喜欢吃红柚子1 小时前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
ZHOU西口1 小时前
微服务实战系列之玩转Docker(十八)
分布式·docker·云原生·架构·数据安全·etcd·rbac
小馒头学python1 小时前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
zmd-zk1 小时前
kafka+zookeeper的搭建
大数据·分布式·zookeeper·中间件·kafka
神奇夜光杯1 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
千天夜1 小时前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流