Locust小结
Posted zouzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Locust小结相关的知识,希望对你有一定的参考价值。
Locust小结
背景
目前网上的教程基本都是1.0之前的,locust丛1.0版本就发生了较多的变化,网上的教程基本不可用。目前locust版本是1.1.1,以下的说明都是针对1.1.1来进行的。
locust适用情景
- 需要逻辑判断但不复杂的请求,并持续化存储
- 压测过程要求不严格,例如相对复杂的步进式放量
- 已有专门的压测指标采集方式,locust提供的监控很鸡肋
locust新特性
如果你不想知道改动点,可以之间跳过这块。
1、HttpLocust的更新
旧版本使用的是TaskSet进行任务或者请求编写,然后在使用HttpLocust进行任务或者请求声明,以及基础属性配置,一般会进行思考时间、host、task_set设置任务类等;
新版本将HttpLocust重写成User,并且HttpUser继承于User,所以推荐使用HttpUser进行任务声明;
另外TaskSet中的task_set已被删除,如果仍要使用TaskSet,则需要在HttpUser中使用tasks进行存储,例
# -*- coding: utf-8 -*-
from locust import HttpUser, task, between, TaskSet
# 采用旧版TaskSet进行定义,不推荐使用,需要在User相关类中定义,才可以被调用
# 补充:SequentialTaskSet是TaskSet子类,作用就是忽略权重,完全根据编写顺序来控制任务执行顺序,多用于事务压测
class TestBaiduSearch2(TaskSet):
def on_start(self):
self.header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
self.payload = {
"wd": "selenium",
}
@task
def search(self):
baidu_response = self.client.get(url="/s", params=self.payload, verify=True, headers=self.header)
print(baidu_response.url)
# 新版建议都使用HttpUser进行定义
class TestBaiDuSearch(HttpUser):
host = "https://www.baidu.com" # 设置host,如果脚本仅是在本地运行或者基本不变的,建议直接脚本固定,反之在启动运行是加入host参数
tasks = [TestBaiduSearch2] # 添加任务
wait_time = between(100, 200) # 设置思考时间范围
def on_start(self):
self.payload = {
"wd": "locust",
}
self.header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
@task
def search(self):
# 默认采用的requests模块的session,这块不做赘述,自行查找
baidu_response = self.client.get(url="/s", params=self.payload, verify=True, headers=self.header)
print(baidu_response.url)
if __name__ == ‘__main__‘:
import os
# 启动脚本,以最大请求5个,每秒步进为1
os.system("locust -f test11.py --headless -u 5 -r 1")
2、任务标记
请求方法进行标志,@tag进行装饰,在启动参数时可以进行选择启动或者排除
class TestBaiDuSearch(HttpUser):
# 命令行启动就可使用--tags(-T)和--exclude-tags(-E)指定启动/排除任务
@task
@tag("https","baidu")
def search(self):
baidu_response = self.client.get(url="/s", params=self.payload, verify=True, headers=self.header)
print(baidu_response.url)
启动标志为『https』的任务
locust -f test11.py --host https://www.baidu.com --tags https
3、环境变量变量名修改
LOCUST_MASTER -> LOCUST_MODE_MASTER
LOCUST_SLAVE -> LOCUST_MODE_WORKER
LOCUST_MASTER_PORT -> LOCUST_MASTER_NODE_PORT
LOCUST_MASTER_HOST -> LOCUST_MASTER_NODE_HOST
CSVFILEBASE -> LOCUST_CSV
4、其他变动
4.1 从机的命令行参数改变为--worker,--expect-workers
4.2 无Web模式的命令行参数改变为--headless
4.3 钩子函数统一使用events进行绑定
...
locust使用
简单介绍
locust是基于python开发的一个协程请求库,协程又称微线程,多个协程可以只运行在一个线程中,由开发者自行选择切换的时机,所以相对于进程、线程拥有更小的资源切换浪费,但由于是运行在python解析器之上的,所以存在GIL锁进制,另外默认的网络请求库还是requests这种同步库,所以单进程下并发不会太高。如果想用locust进行并发请求,必定要使用分布式+异步请求库。
安装
pip install locust 默认安装最新版本
常用写法
# -*- coding: utf-8 -*-
from locust import HttpUser, task, between,tag,SequentialTaskSet,events
# 新版建议都使用HttpUser进行定义
class TestBaiDuSearch(HttpUser):
wait_time = between(0.1, 0.2) # 设置请求的思考时间范围,单位是秒
# weight = 3 任务类权重,越大优先级越高
# tasks =[] 建议少用这个,任务集中控制,非要用大概率是你的设计有问题
# 整体启动执行
@events.test_start.add_listener
def on_test_start(**kwargs):
print("大王我来了!!!")
# 整体结束执行
@events.test_stop.add_listener
def on_test_stop(**kwargs):
print("大王我走了???")
# 每个请求集启动之前进行的操作
def on_start(self):
self.payloadPref = {
"wd": "locust",
}
self.payloadAuto = {
"wd": "selenium",
}
self.header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
print("这就开始了?!")
# 每个请求集结束之后进行的操作
def on_stop(self):
print("这就玩完了?!")
# @task 进行任务标志,里面的数字是权重,权重越大,发起的请求占比越高,如下,相同请求量下,两者比例约3:1
# @tag 进行任务标签注释,可以选择启动或者排查
@task(3)
@tag("baidu")
def searchPref(self):
baidu_response = self.client.get(url="/s", params=self.payloadPref, verify=True, headers=self.header)
# print(baidu_response.url)
@task(1)
def searchAuto(self):
baidu_response = self.client.get(url="/s", params=self.payloadAuto, verify=True, headers=self.header)
# print(baidu_response.url)
if __name__ == ‘__main__‘:
import os
# 启动脚本,以最大请求5个,每秒步进为1
os.system("locust -f test11.py --host https://www.baidu.com --headless -u 5 -r 1")
由于locust默认采用的是requests中的session进行请求发送,所以同样是支持post、put、head等请求方式,详见requests官网
配置化启动
locust不是仅能通过命令行配置启动,如果每次都要写那么长的配置,估计出错的概率也不低,所以locust也提供了配置化启动的形式,这个真的方便!!例:
locust --config=配置文件路径
在脚本同级目录下编写配置文件,baidu.conf
# 脚本路径,目前是在同级目录就直接写文件名了
# 具体的参数有什么还是参考官网给出 https://docs.locust.io/en/stable/configuration.html
locustfile = testbaidu.py
headless = true
host = http://www.baidu.com
users = 6
hatch-rate = 2
run-time = 1m
命令行执行
locust --config=baidu.conf
分布式启动
locust支持一主多从的控制模式,这点也对于单机并发也是一个极大的提升,目前基本都是多核多线程的机器,所以分布式可以充分发挥单机的能力。
推荐单机启动的从机+主机不超过CPU核数,当然你可以试试
首先启动master,默认占用8089端口用于web界面,5557用于从机交互
locust -f testbaidu.py --master
接连启动slave
locust -f testbaidu.py --worker --master-host=127.0.0.1 #此处本地,远程的话使用对应ip即可
浏览器打开 http://127.0.0.1:8089,可见右上角,WORKERS显示的数量与启动的从机数量一致。
注意,界面填写的User量级是总量会均分给每个从机。
locust压测大杀器
前面也多次讲到了locust如果采用了HttpUser,则默认的请求库是使用requests,requests是同步阻塞的请求库,对于压测来说,还是很致命的,每个请求发送完成之后都在响应的回来,即是你机器配置好,也无法充分发挥。
所以locust提供了一个异步请求库,对于代码我们只需将HttpUser改为FastHttpUser即可,前提导入
from locust.contrib.fasthttp import FastHttpUser
另注意,FastHttpUser提供的geventhttpclient其实有坑,比如post请求的data就要求只能是String类型,相对于requests请求还是不太好用。
locust的步进模式
用过jmeter的同学应该都知道,压测一般会采用逐级放量的形式进行请求发送。
同样locust也提供了这种步进默认。
--step-load 启用步进模式
--step-users 每级的用户增量
--step-time 增量间隔
locust -f --headless -u 1000 -r 100 --run-time 30m --step-load --step-users 300 --step-time 1m
无web界面启动locust,设置总用户数1000,每秒增量100个用户,运行总时长30分钟,启动步进模式,步进用户300,维持每个步进模式时间为1分钟
当达到300用户时会维持一分钟,然后在持续增量用户,达到600在维持一分钟,以此类推
locust的其他功能
1、自定义请求对象 https://docs.locust.io/en/stable/testing-other-systems.html
2、扩展Web界面 https://docs.locust.io/en/stable/extending-locust.html
3、将locust作为库来进行使用,调用内部的协程api https://docs.locust.io/en/stable/use-as-lib.html
以上是关于Locust小结的主要内容,如果未能解决你的问题,请参考以下文章