python系列29:压测工具locust

1. 介绍

使用pip进行安装,下面是个简单例子:

from locust import HttpUser, task

class HelloWorldUser(HttpUser):
    @task
    def hello_world(self):
        self.client.get("/hello")
        self.client.get("/world")

然后打开web页面:
在这里插入图片描述点击start,会执行脚本代码,调用hello和world接口。
ramp-up的设置,一般而言:100以内的并发用户数,ramp-up时间设置为1-2s;100-500左右,rramp-up时间设置为2-3s;500以上,ramp-up时间设置为5-10s。
也可以使用命令行:

$ locust --headless --users 10 --spawn-rate 1 -H http://your-server.com
[2021-07-24 10:41:10,947] .../INFO/locust.main: No run time limit set, use CTRL+C to interrupt.
[2021-07-24 10:41:10,947] .../INFO/locust.main: Starting Locust 2.28.0
[2021-07-24 10:41:10,949] .../INFO/locust.runners: Ramping to 10 users using a 1.00 spawn rate
Name              # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
----------------------------------------------------------------------------------------------
GET /hello             1     0(0.00%)  |     115     115     115     115  |    0.00    0.00
GET /world             1     0(0.00%)  |     119     119     119     119  |    0.00    0.00
----------------------------------------------------------------------------------------------
Aggregated             2     0(0.00%)  |     117     115     119     117  |    0.00    0.00

[2021-07-24 10:44:42,484] .../INFO/locust.runners: All users spawned: {"HelloWorldUser": 10} (10 total users)

2. 测试脚本分析

import time
from locust import HttpUser, task, between

class QuickstartUser(HttpUser):
    wait_time = between(1, 5) # 或者可以使用

    @task
    def hello_world(self):
        self.client.get("/hello")
        self.client.get("/world")

    @task(3)
    def view_items(self):
        for item_id in range(10):
            self.client.get(f"/item?id={item_id}", name="/item")
            time.sleep(1)

    def on_start(self):
        self.client.post("/login", json={"username":"foo", "password":"bar"})

脚本中至少需要包含一个class。HttpUser继承自HttpSession,会给每一个用户创建一个self.client。
@task会给每一个用户创建一个greenlet(协程),然后就可以调用clinet的get和post方法来调用http服务:

response = self.client.get("/my-profile")
response = self.client.post("/login", {"username":"testuser", "password":"secret"})

@task中的数值表示权重。每个用户会以权重概率,从所有的task中选取一个执行。
view_items中的name属性,会将所有的url都归类到同一个/item下,而不是分成10个单独的url进行统计。

wait_time除了between还有如下几种:
constant(X):等待固定时间
constant_throughput: for an adaptive time that ensures the task runs (at most) X times per second.
constant_pacing:for an adaptive time that ensures the task runs (at most) once every X seconds
也可以自定义wait_time函数:

class MyUser(User):
    last_wait_time = 0

    def wait_time(self):
        self.last_wait_time += 1
        return self.last_wait_time

@tag标签可以用来指定跑哪些tasks。例如下面的例子中:

from locust import User, constant, task, tag

class MyUser(User):
    wait_time = constant(1)

    @tag('tag1')
    @task
    def task1(self):
        pass

    @tag('tag1', 'tag2')
    @task
    def task2(self):
        pass

    @tag('tag3')
    @task
    def task3(self):
        pass

    @task
    def task4(self):
        pass

If you started this test with --tags tag1, only task1 and task2 would be executed during the test. If you started it with --tags tag2 tag3, only task2 and task3 would be executed.

–exclude-tags will behave in the exact opposite way. So, if you start the test with --exclude-tags tag3, only task1, task2, and task4 will be executed. Exclusion always wins over inclusion, so if a task has a tag you’ve included and a tag you’ve excluded, it will not be executed.

3. 启动函数

如果需要在整个测试开始前或结束后执行代码,则需要下面的函数:

from locust import events

@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    print("A new test is starting")

@events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
    print("A new test is ending")

如果需要在每个process开始前执行一些代码,则需要下面的函数:

from locust import events
from locust.runners import MasterRunner

@events.init.add_listener
def on_locust_init(environment, **kwargs):
    if isinstance(environment.runner, MasterRunner):
        print("I'm on master node")
    else:
        print("I'm on a worker or standalone node")

如果是每次request请求前都要执行一些代码,则需要在User里执行on_start函数:

class QuickstartUser(HttpUser):
    def on_start(self):
        self.client.post("/login", json={"username":"foo", "password":"bar"})

4. FastHttpUser

FastHttpUser使用了geventhttpclient,性能比基于requests的HttpUser快了数倍。In a best case scenario (doing small requests inside a while True-loop) a single Locust process (limited to one CPU core) can do around 16000 requests per second using FastHttpUser, and 4000 using HttpUser (tested on a 2021 M1 MacBook Pro and Python 3.11)
下面是一个例子:

from locust import FastHttpUser, run_single_user, task
from locust.contrib.fasthttp import RestResponseContextManager
from locust.user.wait_time import constant

from collections.abc import Generator
from contextlib import contextmanager


class MyUser(FastHttpUser):
    host = "https://postman-echo.com"
    wait_time = constant(180)  # be nice to postman-echo.com, and dont run this at scale.

    @task
    def t(self):
        # should work
        with self.rest("GET", "/get", json={"foo": 1}) as resp:
            if resp.js["args"]["foo"] != 1:
                resp.failure(f"Unexpected value of foo in response {resp.text}")

        # should work
        with self.rest("POST", "/post", json={"foo": 1}) as resp:
            if resp.js["data"]["foo"] != 1:
                resp.failure(f"Unexpected value of foo in response {resp.text}")
            # assertions are a nice short way to express your expectations about the response. The AssertionError thrown will be caught
            # and fail the request, including the message and the payload in the failure content.
            assert resp.js["data"]["foo"] == 1, "Unexpected value of foo in response"

        # assertions are a nice short way to validate the response. The AssertionError they raise
        # will be caught by rest() and mark the request as failed

        with self.rest("POST", "/post", json={"foo": 1}) as resp:
            # mark the request as failed with the message "Assertion failed"
            assert resp.js["data"]["foo"] == 2

        with self.rest("POST", "/post", json={"foo": 1}) as resp:
            # custom failure message
            assert resp.js["data"]["foo"] == 2, "my custom error message"

        with self.rest("POST", "/post", json={"foo": 1}) as resp:
            # use a trailing comma to append the response text to the custom message
            assert resp.js["data"]["foo"] == 2, "my custom error message with response text,"

        with self.rest("", "/post", json={"foo": 1}) as resp:
            # assign and assert in one line
            assert (foo := resp.js["foo"])
            print(f"the number {foo} is awesome")

        # rest() catches most exceptions, so any programming mistakes you make automatically marks the request as a failure
        # and stores the callstack in the failure message
        with self.rest("POST", "/post", json={"foo": 1}) as resp:
            1 / 0  # pylint: disable=pointless-statement

        # response isn't even json, but RestUser will already have been marked it as a failure, so we dont have to do it again
        with self.rest("GET", "/") as resp:
            pass

        with self.rest("GET", "/") as resp:
            # If resp.js is None (which it will be when there is a connection failure, a non-json responses etc),
            # reading from resp.js will raise a TypeError (instead of an AssertionError), so lets avoid that:
            if resp.js:
                assert resp.js["foo"] == 2
            # or, as a mildly confusing oneliner:
            assert not resp.js or resp.js["foo"] == 2

        # 404
        with self.rest("GET", "http://example.com/") as resp:
            pass

        # connection closed
        with self.rest("POST", "http://example.com:42/", json={"foo": 1}) as resp:
            pass


# An example of how you might write a common base class for an API that always requires
# certain headers, or where you always want to check the response in a certain way
class RestUserThatLooksAtErrors(FastHttpUser):
    abstract = True

    @contextmanager
    def rest(self, method, url, **kwargs) -> Generator[RestResponseContextManager, None, None]:
        extra_headers = {"my_header": "my_value"}
        with super().rest(method, url, headers=extra_headers, **kwargs) as resp:
            if resp.js and "error" in resp.js and resp.js["error"] is not None:
                resp.failure(resp.js["error"])
            yield resp


class MyOtherRestUser(RestUserThatLooksAtErrors):
    host = "https://postman-echo.com"
    wait_time = constant(180)  # be nice to postman-echo.com, and dont run this at scale.

    @task
    def t(self):
        with self.rest("GET", "/") as _resp:
            pass


if __name__ == "__main__":
    run_single_user(MyUser)

5. 其他参数

locust --help
Usage: locust [options] [UserClass ...]

Common options:
  -h, --help            show this help message and exit
  -f <filename>, --locustfile <filename>
                        The Python file or module that contains your test,
                        e.g. 'my_test.py'. Accepts multiple comma-separated
                        .py files, a package name/directory or a url to a
                        remote locustfile. Defaults to 'locustfile'.
  --config <filename>   File to read additional configuration from. See https:
                        //docs.locust.io/en/stable/configuration.html#configur
                        ation-file
  -H <base url>, --host <base url>
                        Host to load test, in the following format:
                        https://www.example.com
  -u <int>, --users <int>
                        Peak number of concurrent Locust users. Primarily used
                        together with --headless or --autostart. Can be
                        changed during a test by keyboard inputs w, W (spawn
                        1, 10 users) and s, S (stop 1, 10 users)
  -r <float>, --spawn-rate <float>
                        Rate to spawn users at (users per second). Primarily
                        used together with --headless or --autostart
  -t <time string>, --run-time <time string>
                        Stop after the specified amount of time, e.g. (300s,
                        20m, 3h, 1h30m, etc.). Only used together with
                        --headless or --autostart. Defaults to run forever.
  -l, --list            Show list of possible User classes and exit
  --config-users [CONFIG_USERS ...]
                        User configuration as a JSON string or file. A list of
                        arguments or an Array of JSON configuration may be
                        provided

Web UI options:
  --web-host <ip>       Host to bind the web interface to. Defaults to '*'
                        (all interfaces)
  --web-port <port number>, -P <port number>
                        Port on which to run web host
  --headless            Disable the web interface, and start the test
                        immediately. Use -u and -t to control user count and
                        run time
  --autostart           Starts the test immediately (like --headless, but
                        without disabling the web UI)
  --autoquit <seconds>  Quits Locust entirely, X seconds after the run is
                        finished. Only used together with --autostart. The
                        default is to keep Locust running until you shut it
                        down using CTRL+C
  --web-login           Protects the web interface with a login page. See
                        https://docs.locust.io/en/stable/extending-
                        locust.html#authentication
  --tls-cert <filename>
                        Optional path to TLS certificate to use to serve over
                        HTTPS
  --tls-key <filename>  Optional path to TLS private key to use to serve over
                        HTTPS
  --class-picker        Enable select boxes in the web interface to choose
                        from all available User classes and Shape classes

Master options:
  Options for running a Locust Master node when running Locust distributed. A Master node need Worker nodes that connect to it before it can run load tests.

  --master              Launch locust as a master node, to which worker nodes
                        connect.
  --master-bind-host <ip>
                        IP address for the master to listen on, e.g
                        '192.168.1.1'. Defaults to * (all available
                        interfaces).
  --master-bind-port <port number>
                        Port for the master to listen on. Defaults to 5557.
  --expect-workers <int>
                        Delay starting the test until this number of workers
                        have connected (only used in combination with
                        --headless/--autostart).
  --expect-workers-max-wait <int>
                        How long should the master wait for workers to connect
                        before giving up. Defaults to wait forever
  --enable-rebalancing  Re-distribute users if new workers are added or
                        removed during a test run. Experimental.

Worker options:
  Options for running a Locust Worker node when running Locust distributed.
  Typically ONLY these options (and --locustfile) need to be specified on workers, since other options (-u, -r, -t, ...) are controlled by the master node.

  --worker              Set locust to run in distributed mode with this
                        process as worker. Can be combined with setting
                        --locustfile to '-' to download it from master.
  --processes <int>     Number of times to fork the locust process, to enable
                        using system. Combine with --worker flag or let it
                        automatically set --worker and --master flags for an
                        all-in-one-solution. Not available on Windows.
                        Experimental.
  --master-host <hostname>
                        Hostname of locust master node to connect to. Defaults
                        to 127.0.0.1.
  --master-port <port number>
                        Port to connect to on master node. Defaults to 5557.

Tag options:
  Locust tasks can be tagged using the @tag decorator. These options let specify which tasks to include or exclude during a test.

  -T [<tag> ...], --tags [<tag> ...]
                        List of tags to include in the test, so only tasks
                        with at least one matching tag will be executed
  -E [<tag> ...], --exclude-tags [<tag> ...]
                        List of tags to exclude from the test, so only tasks
                        with no matching tags will be executed

Request statistics options:
  --csv <filename>      Store request stats to files in CSV format. Setting
                        this option will generate three files:
                        <filename>_stats.csv, <filename>_stats_history.csv and
                        <filename>_failures.csv. Any folders part of the
                        prefix will be automatically created
  --csv-full-history    Store each stats entry in CSV format to
                        _stats_history.csv file. You must also specify the '--
                        csv' argument to enable this.
  --print-stats         Enable periodic printing of request stats in UI runs
  --only-summary        Disable periodic printing of request stats during
                        --headless run
  --reset-stats         Reset statistics once spawning has been completed.
                        Should be set on both master and workers when running
                        in distributed mode
  --html <filename>     Store HTML report to file path specified
  --json                Prints the final stats in JSON format to stdout.
                        Useful for parsing the results in other
                        programs/scripts. Use together with --headless and
                        --skip-log for an output only with the json data.

Logging options:
  --skip-log-setup      Disable Locust's logging setup. Instead, the
                        configuration is provided by the Locust test or Python
                        defaults.
  --loglevel <level>, -L <level>
                        Choose between DEBUG/INFO/WARNING/ERROR/CRITICAL.
                        Default is INFO.
  --logfile <filename>  Path to log file. If not set, log will go to stderr

Other options:
  --show-task-ratio     Print table of the User classes' task execution ratio.
                        Use this with non-zero --user option if some classes
                        define non-zero fixed_count attribute.
  --show-task-ratio-json
                        Print json data of the User classes' task execution
                        ratio. Use this with non-zero --user option if some
                        classes define non-zero fixed_count attribute.
  --version, -V         Show program's version number and exit
  --exit-code-on-error <int>
                        Sets the process exit code to use when a test result
                        contain any failure or error. Defaults to 1.
  -s <number>, --stop-timeout <number>
                        Number of seconds to wait for a simulated user to
                        complete any executing task before exiting. Default is
                        to terminate immediately. When running distributed,
                        this only needs to be specified on the master.
  --equal-weights       Use equally distributed task weights, overriding the
                        weights specified in the locustfile.

User classes:
  <UserClass1 UserClass2>
                        At the end of the command line, you can list User
                        classes to be used (available User classes can be
                        listed with --list). LOCUST_USER_CLASSES environment
                        variable can also be used to specify User classes.
                        Default is to use all available User classes

Examples:

    locust -f my_test.py -H https://www.example.com

    locust --headless -u 100 -t 20m --processes 4 MyHttpUser AnotherUser

See documentation for more details, including how to set options using a file or environment variables: https://docs.locust.io/en/stable/configuration.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/680189.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度剖析可视化大屏的技术架构

在当今信息化时代&#xff0c;可视化大屏作为一种重要的信息展示方式&#xff0c;广泛应用于监控指挥中心、数据分析展示等领域。其技术架构对于保障大屏系统的稳定性和性能至关重要。本文将深入探讨可视化大屏的技术架构&#xff0c;包括硬件架构、软件架构和数据架构等方面&a…

电位器、金属触摸传感器、红外避障传感器、烟雾传感器、倾斜开关传感器 | 配合Arduino使用案例

电位器 电位器就是一个旋转按钮&#xff0c;可以读取到开关旋转的数值&#xff08;范围&#xff1a;0-1023&#xff09; /****** Arduino 接线 ***** VCC - 5v* GND - GND* OUT - A0***********************/int mainPin A0; // 接继电器的 IN 端口void setup() { Serial.be…

提示词工程基础:定义与重要性

目录 一、引言二、提示词工程的定义1. 概念明晰2. 技术框架3. 功能作用 三、提示词工程的重要性1. 核心作用强调2. 提升效率与降低成本3. 推动技术发展与创新 四、提示词工程的组成部分1. 提示词设计2. 模型训练与调整3. 效果评估与优化 五、实际应用示例1. 虚拟助手2. 自动新闻…

【Python数据分析--Numpy库】Python数据分析Numpy库学习笔记,Python数据分析教程,Python数据分析学习笔记(小白入门)

一&#xff0c;Numpy教程 给大家推荐一个很不错的笔记&#xff0c;个人长期学习过程中整理的 Python超详细的学习笔记共21W字点我获取 1-1 安装 1-1-1 使用已有的发行版本 对于许多用户&#xff0c;尤其是在 Windows 上&#xff0c;最简单的方法是下载以下的 Python 发行版…

了解一下Ubuntu Linux

1.3.1 什么是Ubuntu Ubuntu这个名字非常神奇&#xff0c;它取自非洲南部祖鲁语的ubuntu&#xff0c;是一个哲学名称&#xff0c;其意思为“人性”或者“我的存在是因为大家的存在”。对于中国人来说&#xff0c;一般称呼它为乌班图。 Ubuntu是在Debian的基础上开发出来的&am…

qt dragEnterEvent dragLeaveEvent dragMoveEvent dropEvent都不响应的问题解决方案。

环境&#xff1a;vs2019qt5.14.2 坑哦。让我搞了好久。各种不执行&#xff0c;最后发现,不用vs调制&#xff0c;直接运行exe就能接收拖拽了。 记录一下,感觉是qt的bug。上代码。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QText…

算法金 | 再见,PCA 主成分分析!

​大侠幸会&#xff0c;在下全网同名[算法金] 0 基础转 AI 上岸&#xff0c;多个算法赛 Top [日更万日&#xff0c;让更多人享受智能乐趣] 1. 概念&#xff1a;数据降维的数学方法 定义 主成分分析&#xff08;PCA&#xff09;是一种统计方法&#xff0c;通过正交变换将一组可…

大模型卷出新高度|暴雨AI服务器M8878助解算力之困

当今世界&#xff0c;作为新一轮科技革命和产业革命的重要驱动力&#xff0c;AI已经成为“兵家必争之地”。我国也在政府报告中首次将“人工智能”行动纳入国家战略&#xff0c;开启了以人工智能为核心的数字经济高质量发展的新时代。 当今世界&#xff0c;作为新一轮科技革命…

超越传统AI 新型多智能体系统MESA,探索效率大幅提升

探索多智能体强化学习的协同元探索 —— MESA 算法深度解读在多智能体强化学习&#xff08;MARL&#xff09;的征途中&#xff0c;如何高效探索以发现最优策略一直是研究者们面临的挑战。特别是在稀疏奖励的环境中&#xff0c;这一问题变得更加棘手。《MESA: Cooperative Meta-…

计算机基础(5)——进制与进制转换

&#x1f497;计算机基础系列文章&#x1f497; &#x1f449;&#x1f340;计算机基础&#xff08;1&#xff09;——计算机的发展史&#x1f340;&#x1f449;&#x1f340;计算机基础&#xff08;2&#xff09;——冯诺依曼体系结构&#x1f340;&#x1f449;&#x1f34…

群体优化算法---灰狼优化算法学习介绍以及在卷积神经网络训练上的应用

**长文预警**介绍 在自然界中&#xff0c;狼群的社会结构和捕猎策略展现了高度的智能和协调性&#xff0c;灰狼优化算法&#xff08;Grey Wolf Optimizer, GWO&#xff09;正是受此启发提出的一种群体智能优化算法。GWO主要模拟了灰狼的社会等级制度和捕猎行为&#xff0c;其核…

WLAN基础-WLAN安全

目录 一、引言二、WLAN安全威胁三、WLAN安全防御机制四、WLAN常用接入认证方式五、总结 一、引言 随着无线网络的广泛应用&#xff0c;WLAN&#xff08;无线局域网&#xff09;因其灵活性和便利性成为越来越多用户和企业首选的接入方式。然而&#xff0c;由于无线通信开放的传…

R语言探索与分析17-CPI的分析和研究

一、选题背景 CPI&#xff08;居民消费价格指数&#xff09;作为一个重要的宏观经济指标&#xff0c;扮演着评估通货膨胀和居民生活水平的关键角色。在湖北省这个经济活跃的地区&#xff0c;CPI的波动对于居民生活、企业经营以及政府宏观经济政策制定都具有重要的影响。因此&a…

ProtoSprite: Rapid 2D Art

✨ 概述 直接在场景视图中的场景上下文中快速创建、绘制和编辑精灵。以最小的摩擦和紧密的Unity集成快速制作2D艺术。 直接编辑PNG纹理文件,与其他软件广泛兼容。无需担心自定义文件格式或额外的组件。无缝集成到您的项目中,不会造成不必要的混乱。 增强您的二维艺术工作流程…

如何规避亚马逊测评的风险?

国外的真实刷手和服务商的账号风险主要是表现在以下几点&#xff1a; 1. 账号资源的重复利用&#xff0c;下单的产品上一秒高端品牌&#xff0c;下一秒地摊货&#xff0c;对账号的标签定位不清晰 2. 留Review的时间周期长 3. 账号的质量会参差不齐&#xff0c;有的上不了评价…

AI 正在攻克难题——赋予计算机嗅觉

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

python中如何使用密码字典

使用itertools循环迭代的模块来实现生成密码字典&#xff0c;用这个模块可以省不少事。 首先要调用itertools。 import itertools as its 然后将字典需要的元素&#xff08;或者说是关键字&#xff09;赋给word变量。 我们这里假设密码是纯数字&#xff0c;所以元素就是12345…

贷款行业新宠:短信群发营销的高效应用

在贷款行业的激烈竞争中&#xff0c;短信群发营销凭借其高效、精准的特性逐渐崭露头角&#xff0c;成为行业新宠。 一、个性化信息&#xff0c;直达目标客户 通过短信群发&#xff0c;贷款机构能够精准地向目标客户推送个性化的贷款产品推荐。基于客户的信用状况、贷款需求等…

嘉立创EDA隐藏铺铜

在设计PCB时&#xff0c;如果在铺铜后进行部分线路的修改、调试与检查&#xff0c;会比较困难。如果对铺铜进行隐藏后&#xff0c;可极大的方便观察与设计。 嘉立创EDA隐藏铺铜方法如下&#xff1a; 1、打开左侧的过滤选项&#xff0c;在轮廓对象下&#xff0c;关闭铺铜区域选…

LabVIEW储油罐监控系统

LabVIEW储油罐监控系统 介绍了基于LabVIEW的储油罐监控系统的设计与实施。系统通过集成传感器技术和虚拟仪器技术&#xff0c;实现对储油罐内液位和温度的实时监控&#xff0c;提高了油罐监管的数字化和智能化水平&#xff0c;有效增强了油库安全管理的能力。 项目背景 随着…