zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    AOV网和AOE网对比
    AOV网和AOE网对比
    Python类型总结
    Python数据结构
    Django之认证系统
    day22笔记
    数据库概念知识
    pymsql模块使用
    多表查询(子查询)
    多表查询(链接查询)
  • 原文地址:https://www.cnblogs.com/hanxiaobei/p/14993707.html
Copyright © 2011-2022 走看看