2021年中旬就计划着搭建一套压测系统,大约9月份已经搭建完成,使用至今还是比较稳定了,分享一下搭建思路及过程:

为什么选择Locust呢,因为Locust可以仅需要执行命令就可以完成压测任务,并且集群压测也很简单,只需压测机安装locust并把压测脚本推送到服务器即可。

Locust QQ群:

画了一个大致的思路图:

我们说的全链路其实有几层意思:

1.多接口多场景,而非单接口或单url

2.按照用户访问场景及频率,用户访问的路径是有先后的,访问的接口频率也是不一样的。怎么理解这个呢,很简单,比如获取列表的接口(get_list)和获取内容的接口(get_content),用户访问任何页面有可能都会访问

get_list,但用户可能都不会点击详情,所以调用get_list的频率会更多。

怎么真实的获取到用户访问的链路场景呢?

1.通过用户访问的日志,分析用户的行为,然后编写压测场景用例

2.模拟用户场景,导出用户记录
  A.浏览器直接导出记录生成.har文件

  B.app通过抓包工具获取用户记录导出生成.har文件

当然有的人说har文件解析生成接口后,后续压测能一直有效么,比如token等校验通不过,解决这个问题很简单,和研发商量一下,请求参数里加每个值或对特定设备或标识放开就行,后续一路畅通无阻。

压测脚本来源有了,第二步就是解析har文件,模块库里有解析har的,但发现不满足自己使用,自己写吧,项目结构仅供参考:

解析Har文件:

 1 # -*- coding = utf-8 -*-
2 # ------------------------------
3 # @time: 2021/3/22 14:53
4 # @Author: drew_gg
5 # @File: disassemble_har.py
6 # @Software: cover_app_platform
7 # ------------------------------
8
9 import json
10 from app.locust.anasiysis_har import judgment_exist as jud
11 from app.locust.anasiysis_har import deal_headers as dh
12 from app.locust.anasiysis_har import deal_request_data as dr
13 from app.config.har_to_api import api_filter as af
14
15
16 key_words = af.key_words
17
18
19 def disassemble_har(har_file, api_only=0):
20 """
21 提取分解har文件
22 :param har_file: .har文件
23 :param api_only: 1:去重,其他:不去重
24 :return:
25 """
26
27 req_l = []
28 rdl = []
29 rdl_set = []
30 host = ''
31 count = 1
32 # url过滤非接口请求
33 with open(har_file, "r", encoding='utf-8') as f:
34 f = json.loads(f.read())
35 for i in f['log']['entries']:
36 if jud.judgment_exist(i['request']['url'], key_words) is False:
37 req_l.append(i)
38 for index, i in enumerate(req_l):
39 rd = {}
40 # 解析host
41 host = i['request']['url'].split('//')[0] + '//' + i['request']['url'].split('//')[1].split('/')[0]
42 # 解析子url
43 # son_url = i['request']['url'].split(host)[1].split('&')[0]
44 son_url = i['request']['url'].split(host)[1]
45 deal_url = son_url.split('?')[0]
46 if deal_url == '/':
47 if len(son_url.split('?'))> 1:
48 deal_url = son_url.split('?')[1]
49 else:
50 deal_url = '/'
51 deal_url = deal_url.replace('/', '_').replace('-', '_').replace('.', '_').strip('_').lstrip('_')
52 if api_only == 1:
53 method_name = 'api_' + deal_url.lower()
54 else:
55 method_name = 'api_' + deal_url.lower() + '_' + str(index)
56 # 解析处理header
57 headers = dh.deal_headers(i['request']['headers'])
58 method = i['request']['method']
59 # 解析处理请求参数
60 if method.upper() == "POST":
61 request_data = dr.deal_request_data(method, i['request']['postData'])
62 if method.upper() == "GET":
63 request_data = '\'' + i['request']['url'].split(son_url)[1] + '\''
64 host = '"' + host + '"'
65 son_url = '"' + son_url + '"'
66 rd['host'] = host
67 rd['url'] = son_url
68 rd['headers'] = headers
69 rd['method'] = method
70 rd['method_name'] = method_name
71 rd['request_data'] = request_data
72 if api_only == 1:
73 # 去重并计数判断
74 if index == 0:
75 rd['count'] = count
76 rdl_set.append(rd)
77 else:
78 for x in rdl_set:
79 if son_url == x['url']:
80 x['count'] += 1
81 count = x['count']
82 else:
83 if count == 1:
84 rd['count'] = count
85 rdl_set.append(rd)
86 count = 1
87 else:
88 rd['count'] = count
89 rdl.append(rd)
90 if api_only != 1:
91 rdl_set = rdl
92 return rdl_set, host
93
94
95 if __name__ == '__main__':
96 har_path = r'D:\thecover_project\cover_app_platform\app\file_upload\首页普通\20210803-113719\syptxq.har'
97 disassemble_har(har_path)

解析har文件,处理header、获取接口必要参数,然后对请求做分析,如果要去重,则统计相同请求的数量,压测时生成压测权重,如果不去重,后续生成压测脚本时则需要对处理方法名称。

解析好har文件后,需要生成调试脚本和压测脚本:

我处理方式实直接生成py文件,事先创建好模板,如:

生成调试脚本比较简单,只需要一个模板就行,生成locust压测脚本则稍微负责点,我是分拆成多个模板,然后整合到一个模板。

生成的脚本都规范放在目录里:

生成脚本目录结构:

生成压测脚本示例:

 1 # -*- coding = utf-8 -*-
2 # ------------------------------
3 # @time: 2021-04-19 13:43:10.380837
4 # @Author: drew_gg
5 # @File: liao_bao.py
6 # @Software: api_locust
7 # ------------------------------
8
9
10 from locust import SequentialTaskSet, task, constant, tag, TaskSet
11 from locust.contrib.fasthttp import FastHttpUser
12
13
14 class LiaoBao20210419(TaskSet):
15
16 @task(1)
17 @tag('api_getlist')
18 def api_getlist(self):
19 headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'tenantId': '7'}
20 # 请求参数组装 ## r_url:固定参数
21 r_url = "/getList?vno=6.4.0"
22 requests_data = {'account': 'E2247B94-51E2-4952-BC06-24752911C060', 'client': 'iOS', 'data': '{"operation_type":0,"news_id":0,xxxxxxxxxxxxxxxxxxx'}
23 # 发起请求
24 with self.client.post(r_url, data=requests_data, catch_response=True, name=r_url) as r:
25 if r.content == b"":
26 r.failure("No data")
27 if r.status_code != 200:
28 em = "request error --" + str(r.status_code)
29 r.failure(em)
30
31 @task(4)
32 @tag('api_getsysnotice')
33 def api_getsysnotice(self):
34 headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'tenantId': '7'}
35 # 请求参数组装 ## r_url:固定参数
36 r_url = "/getSysnotice?vno=6.4.0"
37 requests_data = {'account': 'E251179A-6309-4326-9827-73C892131605', 'client': 'iOS', 'data': '{"page_size":15,"page":1}', xxxxxxxxxxxxxxxxxxxxxxxx}
38 # 发起请求
39 with self.client.post(r_url, data=requests_data, catch_response=True, name=r_url) as r:
40 if r.content == b"":
41 r.failure("No data")
42 if r.status_code != 200:
43 em = "request error --" + str(r.status_code)
44 r.failure(em)
45
46 @task(4)
47 @tag('api_user_preparecancelaccount')
48 def api_user_preparecancelaccount(self):
49 headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'tenantId': '7'}
50 # 请求参数组装 ## r_url:固定参数
51 r_url = "/user/prepareCancelAccount?vno=6.4.0"
52 requests_data = {'account': '2FF3D47C-995B-4D7E-93CD-58B4F1E94B74', 'client': 'iOS', 'data': '{}', xxxxxxxxxxxxxxxxxxxxxxx}
53 # 发起请求
54 with self.client.post(r_url, data=requests_data, catch_response=True, name=r_url) as r:
55 if r.content == b"":
56 r.failure("No data")
57 if r.status_code != 200:
58 em = "request error --" + str(r.status_code)
59 r.failure(em)
60
61
62 class liao_bao_locust(FastHttpUser):
63 host = "https://xxxxxx.xxxxx.com"
64 wait_time = constant(0)
65 tasks = {LiaoBao20210419: 1}

生成好脚本后,需要生成执行命令:

 1 # -*- coding = utf-8 -*-
2 # ------------------------------
3 # @time: 2021/3/3 11:08
4 # @Author: drew_gg
5 # @File: locust_create_cmd.py
6 # @Software: cover_app_platform
7 # ------------------------------
8
9
10 def create_master_cmd(locust_pra):
11 """
12 生成master命令
13 :param locust_pra:
14 :return:
15 """
16 # locust master 命令样式:
17 """
18 locust -f /work/locust/api_locust/locust_view/fm_api/locust_api/locust_fm_640.py
19 --master
20 --master-bind-port 9800
21 --headless
22 -u 600
23 -r 200
24 --expect-worker 16
25 -t 10m
26 -s 10
27 --csv /work/locust/locust_report/fm/locust_get_dynamic.py0223145309
28 --html /work/locust/api_locust/resource/html/new_html/locust_get_operation_parm.html
29 """
30 run_port = '9800'
31 master_cmd = "locust -f %s --master --master-bind-port %s --headless " % (locust_pra['to_file'], run_port)
32 master_pra = "-u %s -r %s --expect-worker %s -t %ss -s 10 --csv %s --html %s > %s" % \
33 (locust_pra['user'], locust_pra['rate'], locust_pra['thread'], locust_pra['time'], locust_pra['csv'],
34 locust_pra['html'], locust_pra['master_log'])
35 master_cmd = master_cmd + master_pra
36 return master_cmd
37
38
39 def create_slave_cmd(locust_pra):
40 """
41 生成slave命令
42 :return:
43 """
44 run_port = '9800'
45 if len(locust_pra['api']) == 1 and locust_pra['api'][0] == '':
46 slave_cmd = "locust -f %s --master-host %s --master-port %s --headless --worker > %s" % \
47 (locust_pra['to_file'], locust_pra['master'].split('-')[0], run_port, locust_pra['slave_log'])
48 else:
49 tags = ''
50 for i in locust_pra['api']:
51 tags += i.split(".py")[0] + ' '
52 slave_cmd = "locust -f %s --master-host %s --master-port %s --headless --worker -T %s > %s" % \
53 (locust_pra['to_file'], locust_pra['master'].split('-')[0], run_port, tags, locust_pra['slave_log'])
54 return slave_cmd

然后把文件推送到服务器上,服务器也需要有规定的目录:

每台压测机上建立三个目录:

master上存储压测生成的报告、csv文件,然后写个定时程序拉去报告到项目服务器,压测完后可直接查询报告。

平台主要界面:

1.首页

2.上传并解析har文件页面

3.压测脚本在线编辑执行页面

4.接口调试页面

5.调试结果页

6.压测配置页面

7.压测执行及记录页面

8.压测报告页面

9.服务器管理页面

大致包含这些功能,当然,项目搭建过程中遇到各种坑,要尝试才知道,后续打算优化一下代码,再升级几个版本,也算彻底搞定。

欢迎感兴趣的一起研究讨论。

基于locust全链路压测系统的更多相关文章

  1. 全链路压测平台(Quake)在美团中的实践

    背景 在美团的价值观中,以“客户为中心”被放在一个非常重要的位置,所以我们对服务出现故障越来越不能容忍.特别是目前公司业务正在高速增长阶段,每一次故障对公司来说都是一笔非常不小的损失.而整个IT基础设 ...

  2. 京东全链路压测军演系统(ForceBot)架构解密

    摘要:全链路压测是应对电商大促容量规划最有效的手段,如何有效进行容量规划是其中的架构关键问题.京东在全链路压测方面做过多年尝试,本文转载京东商城基础平台技术专家文章,介绍其最新的自动化压测 Force ...

  3. 高德全链路压测平台TestPG的架构与实践

    导读 2018年十一当天,高德DAU突破一个亿,不断增长的日活带来喜悦的同时,也给支撑高德业务的技术人带来了挑战.如何保障系统的稳定性,如何保证系统能持续的为用户提供可靠的服务?是所有高德技术人面临的 ...

  4. 【转】京东金融App端链路服务端全链路压测策略

    京东金融移动端全链路压测历时三个月,测试和服务端同学经过无数日日夜夜,通宵达旦,终于完成了移动端链路的测试任务.整个测试有部分涉及到公司敏感数据,本文只对策略部分进行论述. 1.系统架构与策略 在聊性 ...

  5. <转>二十问全链路压测干货汇总(上)

    本文转载自:微信公众号-数列科技<二十问全链路压测干货汇总(上)> 最近几年全链路压测无疑成为了一个热门话题,在各个技术峰会上都可以看到它的身影. 一些大型的互联网公司,比如阿里巴巴.京东 ...

  6. 生产环境全链路压测平台 Takin

    什么是Takin? Takin是基于Java的开源系统,可以在无业务代码侵入的情况下,嵌入到各个应用程序节点,实现生产环境的全链路性能测试,适用于复杂的微服务架构系统. Takin核心原理图 Taki ...

  7. 案例 | 荔枝微课基于 kubernetes 搭建分布式压测系统

    王诚强,荔枝微课基础架构负责人.热衷于基础技术研发推广,致力于提供稳定高效的基础架构,推进了荔枝微课集群化从0到1的发展,云原生架构持续演进的实践者. 本文根据2021年4月10日深圳站举办的[腾讯云 ...

  8. 让全链路压测变得更简单!Takin2.0重磅来袭!

    自Takin社区版1.0发布两个多月以来,有很多测试同学陆续在各自的工作中运用了起来,其中包括金融.电商.物流.出行服务等行业.这个过程中我们收到了很多同学的反馈建议,同时也了解到很多同学在落地全链路 ...

  9. 全链路压测SOP

    压测模型构建:人工 线上(大促)流量数据 (数据脱敏) 日常流量数据 业务方新的特性产生的变更数据 友商做过的事情 压测模型构建:自动 流程包括:录制-清洗-回放 (目前能做好的公司非常少) 压测标准 ...

  10. 美团--Quake全链路压测平台

    原文:连接: https://tech.meituan.com/2018/09/27/quake-introduction.html 开源分布式监控Cat: https://github.com/di ...

随机推荐

  1. AOP+自定义注解实现权限校验-2022新项目

    一.业务场景 当前本人参与开发的是一个业务中台系统,所谓的中台简单的理解就是把相同的功能给抽取出来.比如系统A.B.C.D都需要进行用户登录操作,那么可以把用户信息管理这一块抽取出来为一个独立的系统E ...

  2. win10 vscode 设置 快捷键 ctrl + , ctrl + COMMA 与搜狗输入法 切换方法快捷键 冲突

    win10 vscode 快捷键 ctrl + , ctrl + COMMA 与搜狗输入法 切换方法快捷键 冲突 没想到是在系统里面 Step. 1: 选择切换语音 Step. 2: 选择 键盘 St ...

  3. eclipse插件FindBugs使用笔记

    FindBugs是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题.Findbugs自带检测器,其中有60余种Bad practice,80余种Correct ...

  4. AOSP下载且编译

    一.简介 AOSP:Android Open Source Project 二.环境要求 我们可以先了解官网(https://source.android.com/docs/setup/start/r ...

  5. MapStructPlus 1.2.5 发布,新增 Solon 支持

    MapStructPlus 1.2.5 发布,更新内容如下: fix: 解决 MapConvertMapperAdapter 编译警告问题 feat: 增加 nullValueMappingStrat ...

  6. 【UE虚幻引擎】手把手教学,UE新手打包全攻略!

    UE虚幻引擎是一款强大的3D实时开发工具,可用于游戏开发.建筑及汽车可视化.影视内容创作.广播及现场活动制作.培训及仿真模拟以及其他实时应用.在UE实际开发过程中,新手工程师可能会遇到总是打包失败的情 ...

  7. 【3D可视化】3D可视化在智慧园区的应用

    随着5G运用和新基建政策,构建智慧城市系统成为当下城市管理的热门需求,智慧园区建设的核心是3D可视化平台,利用它可以提高企业园区智能化.3D数字化管理服务水平. 一.智慧园区概念 "3D可视 ...

  8. fyne - 谁说用Go不能开发应用界面

    fyne项目介绍 fyne 是一个纯 Golang 的跨平台 GUI 库,跨平台库说实话,是有很多选择的,Flutter.Electron.QT等.fyne 绝对不是一个很大众的选择.但是在我,一名后 ...

  9. 二次元 & 动漫壁纸网站(内容记录)

    前言 天天和电脑.手机以及平板等电子设备打交道,一个好看的桌面壁纸图片当然是必不可少的,也曾经分享过<值得珍藏的高清壁纸网站推荐>,各种类型和分辨率的壁纸都有. 今天再分享些「高清二次元& ...

  10. Linunx安装wkhtmltox

    1.下载wkhtmltox安装包 官网:https://wkhtmltopdf.org/downloads.html 根据系统类型选择下载wkhtmltox 环境:centos6 32位.wkhtml ...