Locust1.6 从入门到实战

locust是开源的、基于python采用协程能产生高并发的性能测试工具。

一、Locust环境安装

1、非虚拟环境安装:pip install locust(目前版本1.6)

2、虚拟环境安装如下:

 

⚠️注意:虚拟环境的安装必须是在bin目录下进行pip安装!!!

虚拟环境安装完成后如下:

 如果不小心退出了虚拟环境,想重回虚拟环境。首先进入bin目录,source activate即可,如下图所示:

 二、Locust分布式

locust和LR、jmeter类似都可以实现分布式发压。

locust分布式启动场景有2种,一种是单机设置master和worker模式,另外一种是有多个机器,其中一个机器设置master,其它机器设置worker节点。

无论是单机主从模式还是多机主从模式都是先启动 master,然后再逐一启动若干个 worker

1、单机主从模式(又叫多进程运行)

Locust 中使用 master-worker 模式启动多个进程【充分使用多核处理器的处理能力,worker节点数要小于等于本机的处理器数】,如下是Mac和windows的查找方式

 

主节点:locust -f locustfile.py --master 【master不负责运行task任务,只负责做管理,没有日志输出】

从节点:locust -f locustfile.py --worker【多开几个终端可以充分发挥处理器的核数(worker节点数要小于等于本机的处理器数),会显示输出日志

2、多机主从模式

选择其中一台电脑做为master节点。主节点无法操作别的节点,所以必须在其它机器上启动从属Locust节点。启动命令后面跟上--worker参数,以及--master-host(指定主节点的IP/主机名)

主节点:locust -f locustfile.py --master

从节点:locust -f locustfile.py --worker --master-host=192.168.x.xx

三、Locust脚本编写

项目文件结构如下【这里我是在python虚拟环境下文件结构】

 

"""
1、locust特别适合做接口侧性能测试
2、如果要测试的接口不多,也没有执行顺序上的要求,可以单独的写成一个方法即可,如下第一种和第二种方式
3、如果要测试的接口多,有权重的执行要求,这时候就需要写在一个或多个任务集中,如下第三种方式
写在一个任务集中权重分配:task标记
写在多个任务集中权重分配:
按比例分配A类名是B类名下任务的3倍
tasks = {A: 3, B: 1}
4、第一种,第二种、第三种都是并行执行,多个类【任务集】运行:tasks = [A, B]
5、第四种按一定的顺序执行[TaskSet.SequentialTaskSet]
6、参数化取值方式:
循环取数据,数据可重复使用 list(无序)
保证并发测试数据唯一性,循环取值 queue(有序)
保证并发测试数据唯一性,不循环取值 queue(有序)
7、关联可采用common中正则提取所要的字符串
8、分布式压测:协程在Linux下性能要比windows好很多的,可以设置windows为master,Linux下为worker节点
"""

  1 import queue
  2 from queue import Queue
  3 from random import choice
  4 from locust import HttpUser, constant, between, task, TaskSet, tag, SequentialTaskSet
  5 from locust import HttpLocust  # 1.0版本之前在使用HttpLocust
  6 # ======================
  7 # #第二种写在用户类外定义函数
  8 # @task
  9 # def http_get(user):
 10 #     user.client.request(method='GET', url="/getAllUrl", name='打开首页')
 11 
 12 
 13 # ======================
 14 # #第三种写在任务类中
 15 # 任务类
 16 class ApiTask(TaskSet):
 17     @task
 18     def http_get(self):
 19         self.client.get("/getAllUrl")
 20 
 21     @task(5)
 22     def http_post(self):
 23         header = {"Content-Type": "application/json"}
 24         payload = {
 25             "page": 1,
 26             "count": 200
 27         }
 28         with self.client.post("/getWangYiNews", headers=header, data=payload, verify=False, name="获取200条信息")as res:
 29             print(res.text)
 30 
 31 
 32 # ======================
 33 # #第四种写在任务类中并按一定顺序执行,SequentialTaskSet是TaskSet类下的按顺序执行的一个函数
 34 # 任务类
 35 class ApiSeqTask(SequentialTaskSet):
 36     # @task
 37     # def http_get(self):
 38     #     self.client.get("/getAllUrl", name="获取所有URL")
 39 
 40     # @task(10)
 41     # def http_post(self):
 42     #     # post请求无序参数化取值
 43     #     p_c = choice(self.user.payload).split(",")
 44     #     print(p_c)
 45     #     header = {"Content-Type": "application/json"}
 46     #     payload = {
 47     #         "page": p_c[0],
 48     #         "count": p_c[1]
 49     #     }
 50     #     with self.client.post("/getWangYiNews", headers=header, data=payload, verify=False, name="获取200条信息")as res:
 51     #         print(res.text)
 52 
 53     # @task
 54     # def http_get(self):
 55     #     # 无序请求参数化取值
 56     #     p_c = choice(self.user.payload).split(",")
 57     #     print(p_c)
 58     #     params = {
 59     #         "page": p_c[0],
 60     #         "count": p_c[1]
 61     #     }
 62     #     with self.client.get("/poetryFull", params=params, name="获取诗词")as res:
 63     #         print(res.text)
 64 
 65     @task
 66     def http_get(self):
 67         # 有序请求参数化取值
 68         try:
 69             count_page = self.user.count_page.get()  # 获取唯一的配置信息
 70             print(count_page)
 71         except queue.Empty:
 72             print("数据已用完")
 73             exit(0)  # 无错误退出
 74         countpage = count_page.split(",")
 75         params = {
 76             "page": countpage[0],
 77             "count": countpage[1]
 78         }
 79         with self.client.get("/poetryFull", params=params, name="获取诗词")as res:
 80             print(res.text)
 81 
 82 
 83 # 用户类
 84 # 定义一个类并继承locust下的HttpUser类
 85 class ApiUser(HttpUser):
 86     # host = "http://api.apiopen.top"  # 设置网站的根地址
 87     host = "http://poetry.apiopen.top"  # 设置网站的根地址
 88 
 89     # 格式一
 90     # wait_time = constant(3)     # 每次请求的固定停顿时间(相当于性能测试的思考时间)
 91     # 格式二
 92     # wait_time = between(2, 5)     # 每次请求的停顿时间在2到5秒之间随机取值(也相当于性能测试的思考时间)
 93     # 格式三
 94     min_wait = 2000               # 模拟负载任务之间执行时的 最小/最大 停顿时间,单位毫秒
 95     max_wait = 5000
 96 
 97     # tasks = [http_get]            # 与第二种方式结合使用,ApiUser类继承了HttpUser,tasks任务集中也继承了user
 98     # tasks = [ApiTask]             # 与第三种方式结合使用,tasks任务集后也可以是类
 99     tasks = [ApiSeqTask]             # 与第四种方式结合使用,执行一次get请求再执行十次post请求
100 
101     # ======================
102     # 第一种直接写在用户类下定义函数
103     # @task  # task括号内数值越大执行频率越高,默认标记为1
104     # def http_get(self):
105     #     self.client.request(method='GET', url = "/getAllUrl", name='打开首页')
106 
107     # 无序参数化
108     payload = []
109     with open("data/id.csv",'r')as file:
110         for line in file.readlines():
111             payload.append(line.strip())
112     # print(payload) # ['1,200', '2,100', '3,50', '4,10', '5,5']
113 
114     # 有序参数化
115     count_page = Queue()
116     with open("data/id.csv",'r')as file:
117         for line in file.readlines():
118             count_page.put_nowait(line.strip())

 tools文件内容及data下数据:

 1 """
 2 工具:正则匹配出想要的参数,可以用在关联中
 3 """
 4 import re
 5 
 6 
 7 def fetch_String(data, LB = None, RB = None):
 8     rule = LB + r"(.*?)" + RB
 9     slot_list = re.findall(rule, data)
10     return slot_list
1 1,2
2 2,1
3 3,5
4 4,1
5 5,3

 

本文扩展阅读:

locust官方文档:https://docs.locust.io/en/stable/quickstart.html

requests官方文档:https://docs.python-requests.org/zh_CN/latest/

念师系列:https://www.missshi.cn/?s=Locust#/blogGroupDetail/29?_k=f0iyqp

posted @ 2021-07-10 13:57  韩凯1990  阅读(386)  评论(0编辑  收藏  举报