python系列29:压测工具locust

1. 介绍

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

from locust import HttpUser, taskclass HelloWorldUser(HttpUser):@taskdef 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, betweenclass QuickstartUser(HttpUser):wait_time = between(1, 5) # 或者可以使用@taskdef 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 = 0def wait_time(self):self.last_wait_time += 1return self.last_wait_time

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

from locust import User, constant, task, tagclass MyUser(User):wait_time = constant(1)@tag('tag1')@taskdef task1(self):pass@tag('tag1', 'tag2')@taskdef task2(self):pass@tag('tag3')@taskdef task3(self):pass@taskdef 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 constantfrom collections.abc import Generator
from contextlib import contextmanagerclass MyUser(FastHttpUser):host = "https://postman-echo.com"wait_time = constant(180)  # be nice to postman-echo.com, and dont run this at scale.@taskdef t(self):# should workwith 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 workwith 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 failedwith self.rest("POST", "/post", json={"foo": 1}) as resp:# mark the request as failed with the message "Assertion failed"assert resp.js["data"]["foo"] == 2with self.rest("POST", "/post", json={"foo": 1}) as resp:# custom failure messageassert 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 messageassert 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 lineassert (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 messagewith 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 againwith self.rest("GET", "/") as resp:passwith 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# 404with self.rest("GET", "http://example.com/") as resp:pass# connection closedwith 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@contextmanagerdef 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 respclass MyOtherRestUser(RestUserThatLooksAtErrors):host = "https://postman-echo.com"wait_time = constant(180)  # be nice to postman-echo.com, and dont run this at scale.@taskdef t(self):with self.rest("GET", "/") as _resp:passif __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 aremote locustfile. Defaults to 'locustfile'.--config <filename>   File to read additional configuration from. See https://docs.locust.io/en/stable/configuration.html#configuration-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 usedtogether with --headless or --autostart. Can bechanged during a test by keyboard inputs w, W (spawn1, 10 users) and s, S (stop 1, 10 users)-r <float>, --spawn-rate <float>Rate to spawn users at (users per second). Primarilyused 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 ofarguments or an Array of JSON configuration may beprovidedWeb 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 testimmediately. Use -u and -t to control user count andrun time--autostart           Starts the test immediately (like --headless, butwithout disabling the web UI)--autoquit <seconds>  Quits Locust entirely, X seconds after the run isfinished. Only used together with --autostart. Thedefault is to keep Locust running until you shut itdown using CTRL+C--web-login           Protects the web interface with a login page. Seehttps://docs.locust.io/en/stable/extending-locust.html#authentication--tls-cert <filename>Optional path to TLS certificate to use to serve overHTTPS--tls-key <filename>  Optional path to TLS private key to use to serve overHTTPS--class-picker        Enable select boxes in the web interface to choosefrom all available User classes and Shape classesMaster 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 nodesconnect.--master-bind-host <ip>IP address for the master to listen on, e.g'192.168.1.1'. Defaults to * (all availableinterfaces).--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 workershave connected (only used in combination with--headless/--autostart).--expect-workers-max-wait <int>How long should the master wait for workers to connectbefore giving up. Defaults to wait forever--enable-rebalancing  Re-distribute users if new workers are added orremoved 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 thisprocess 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 enableusing system. Combine with --worker flag or let itautomatically set --worker and --master flags for anall-in-one-solution. Not available on Windows.Experimental.--master-host <hostname>Hostname of locust master node to connect to. Defaultsto 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 taskswith at least one matching tag will be executed-E [<tag> ...], --exclude-tags [<tag> ...]List of tags to exclude from the test, so only taskswith no matching tags will be executedRequest statistics options:--csv <filename>      Store request stats to files in CSV format. Settingthis option will generate three files:<filename>_stats.csv, <filename>_stats_history.csv and<filename>_failures.csv. Any folders part of theprefix 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 runningin 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 otherprograms/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, theconfiguration is provided by the Locust test or Pythondefaults.--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 stderrOther options:--show-task-ratio     Print table of the User classes' task execution ratio.Use this with non-zero --user option if some classesdefine non-zero fixed_count attribute.--show-task-ratio-jsonPrint json data of the User classes' task executionratio. Use this with non-zero --user option if someclasses 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 resultcontain any failure or error. Defaults to 1.-s <number>, --stop-timeout <number>Number of seconds to wait for a simulated user tocomplete any executing task before exiting. Default isto terminate immediately. When running distributed,this only needs to be specified on the master.--equal-weights       Use equally distributed task weights, overriding theweights specified in the locustfile.User classes:<UserClass1 UserClass2>At the end of the command line, you can list Userclasses to be used (available User classes can belisted with --list). LOCUST_USER_CLASSES environmentvariable can also be used to specify User classes.Default is to use all available User classesExamples:locust -f my_test.py -H https://www.example.comlocust --headless -u 100 -t 20m --processes 4 MyHttpUser AnotherUserSee documentation for more details, including how to set options using a file or environment variables: https://docs.locust.io/en/stable/configuration.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大尺寸图像分类检测分割统一模型:Resource Efficient Perception for Vision Systems

论文题目&#xff1a;Resource Efficient Perception for Vision Systems 论文链接&#xff1a;http://arxiv.org/abs/2405.07166 代码链接&#xff1a;https://github.com/Visual-Conception-Group/Localized-Perception-Constrained-Vision-Systems 作者设计了一个统一的模…

k8s牛客面经篇

k8s的pod版块: k8s的网络版块: k8s的deployment版块: k8s的service版块: k8s的探针板块: k8s的控制调度板块: k8s的日志监控板块: k8s的流量转发板块: k8s的宏观版块:

单列集合--collection

package exercise;import java.util.ArrayList; import java.util.Collection;public class CollectionDemo {public static void main(String[] args) {//注意点://Co1lection是一个接口,我们不能直接创建他的对象。//所以&#xff0c;现在我们学习他的方法时&#xff0c;只能…

【LeetCode算法】第108题:将有序数组转换为二叉搜索树

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路&#xff1a;由于数组nums是递增的&#xff0c;采用二分查找法来构造平衡二叉搜索树。首先&#xff0c;选择nums的中间结点作为根节点&#xff0c;然后将左部分的中间值作为左子树…

中学生学人工智能系列:如何用AI学物理

经常有读者朋友给公众号《人工智能怎么学》留言咨询如何使用人工智能学习语文、数学、英语、化学等科目。这些都是中学教师、中学生朋友及其家长们普遍关注的问题。仅仅使用留言回复的方式&#xff0c;不可能对这些问题做出具体和透彻的解答&#xff0c;因此本公众号近期将推出…

Linux基础 (十二):Linux 线程的创建与同步

本篇博客详细介绍与线程有关的内容&#xff0c;这部分也是笔试面试的重点&#xff0c;需要我们对线程有深刻的理解&#xff0c;尤其是线程的并发运行以及线程同步的控制&#xff01;接下来&#xff0c;让我们走进线程的世界&#xff0c;去理解线程&#xff0c;使用线程&#xf…

kvm学习 - 迅速上手示例

目录 kvmtool kvmsample kvmtool GitHub - kvmtool/kvmtool: Stand-alone Native Linux KVM Tool repoStand-alone Native Linux KVM Tool repo. Contribute to kvmtool/kvmtool development by creating an account on GitHub.https://github.com/kvmtool/kvmtool.git cd …

Wpf 使用 Prism 开发MyToDo应用程序

MyToDo 是使用 WPF &#xff0c;并且塔配Prism 框架进行开发的项目。项目中进行了前后端分离设计&#xff0c;客户端所有的数据均通过API接口获取。适合新手入门学习WPF以及Prism 框架使用。 首页统计以及点击导航到相关模块功能待办事项增删改查功能备忘录增删改查功能登录注册…

Vue渲染函数与JSX指南

title: Vue渲染函数与JSX指南 date: 2024/6/3 下午6:43:53 updated: 2024/6/3 下午6:43:53 categories: 前端开发 tags:Vue渲染JSX基础性能优化组件对比React JSX大项目测试策略 第1章&#xff1a;Vue.js入门 Vue.js的历史和背景 Vue.js是一个用于构建用户界面的JavaScript框…

Java流与链表:探索java.util.stream与LinkedList的交汇点

在现代Java开发中&#xff0c;流&#xff08;Streams&#xff09;和链表&#xff08;LinkedList&#xff09;都是强大且常用的数据处理工具。java.util.stream提供了高效的方式来处理数据流&#xff0c;而LinkedList则是java.util包中的经典集合实现。本文将探索它们的交汇点&a…

【Java】接口详解

接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量。 一个简单的接口代码示例 interface IShape { void draw(); } class Cycle implements IShape { Override public void draw() { System.out.println…

【论文笔记】Content-based Unrestricted Adversarial Attack

图2&#xff1a;Adversarial Content Attack的流程。首先使用Image Latent Mapping将图像映射到潜变量空间。然后&#xff0c;用Adversarial Latent Optimization生成对抗性样本。最后&#xff0c;生成的对抗性样本可以欺骗到目标分类模型。 3.1 Image Latent Mapping 对于扩…

升级 macOS 12 之后,CleanMyMac 闪退怎么办?

​​好多朋友在升级 macOS 12 之后&#xff0c;发现 CleanMyMac 出现闪退问题&#xff0c;这可能是TNT的证书过期造成的&#xff0c;那么如何解决CleanMyMac闪退的问题呢&#xff1f; 今天给大家带来了三种解决方法&#xff0c;如下&#xff1a; 一、打开“终端”&#xff0c;运…

回溯算法常见思路

回溯问题 回溯法&#xff0c;一般可以解决如下几种问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合切割问题&#xff1a;一个字符串按一定规则有几种切割方式子集问题&#xff1a;一个N个数的集合里有多少符合条件的子集排列问题&#xff1a;N个数…

for深入学习

目录 练习&#xff1a; 例1&#xff1a; 求解0-100中整除3的数有哪些 例2&#xff1a; 求0-100中含数字9个个数 作业&#xff1a; 练习&#xff1a; 例1&#xff1a; 求解0-100中整除3的数有哪些 代码&#xff1a; #include<stdio.h> int main() {printf("整…

揭秘!天工AI如何帮我轻松搞定产品经理工作,低调强大

聊到AI搜索&#xff0c;总会想起那句话&#xff1a;“领导者和追随者最大的区别在于创新” 作为一名AI产品经理&#xff0c;我深刻体会到搜索引擎对我们日常生活的重要性&#xff0c;在本文中我将会分享我是如何使用图文并茂的天工AI搜索引擎辅助我完成产品经理的工作。 从最初…

强大的机器学习建模扩展包:mlxtend

公众号&#xff1a;尤而小屋编辑&#xff1a;Peter作者&#xff1a;Peter 大家好&#xff0c;我是Peter~ 今天给大家介绍一个强大的机器学习建模扩展包&#xff1a;mlxtend。 mlxtend(machine learning extensions&#xff0c;机器学习扩展)是一个用于日常数据分析、机器学习…

LeetCode216组合总和3

题目描述 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a;只使用数字1到9。每个数字 最多使用一次。返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 解析 递归加剪枝&#xff0c;搜索长度达…

基于JSP的美食推荐管理系统

你好呀&#xff0c;我是学长猫哥&#xff01;如果有需求可以文末加我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSPJavaBeansServlet 系统展示 首页 用户注册 用户登录 热门美食 摘要 本文介绍了一个基于JSP技术的美食推荐管理系统&#xff0…

企业内业务系统与Activiti流程引擎的结合(十一)

摘要:前文分享了企业内部系统集成Activiti的架构和API设计,这里再介绍下 bpmn 流程图的绘制以及与 流程图与bpm后台服务代码的结合点。 一、画流程图 以使用 eclipse 画流程图为例 1. 将 Activiti BPMN 插件安装到 eclipse 插件安装成本后的效果:新建向导中出现 Activiti…