使用Grafana K6来测测你的系统负载能力

背景

近期我们有个号称会有很高很高并发的系统要上线,为了测试一下自己开发的系统的负载能力,准备了点海克斯科技,来看看抗不抗的住。

之前笔者写过用Apache JMeter进行压力测试的文章(传送门👉:https://xie.infoq.cn/article/9c156894b7374e1bd9bc6271f),这次换成了K6,实在不是因为爱折腾,而因为我们是小团队,没那么多工种,很多事儿基本都是开发自己来,K6在配置上比Jmeter更加简单,而且支持JavaScript脚本,更适合我们的测试场景。

部署环境

安装K6

这部分,其实没什么可多说的,参照官网的手册即可(传送门👉:https://grafana.com/docs/k6/latest/),我是在Ubuntu 22.04系统进行的安装。

*安装vscode

这一步其实可有可无,只是写脚本的话,Linux自带的vi,或者安装一下vim,nano等都完全足够,但我个人还是比较推荐结合vscode的remote-ssh插件,来编写远程服务器上的文件。

尤其是K6的测试脚本是JavaScript脚本,搭配vscode来写的话会更方便一些。

这里安装步骤也不细说了,在vscode插件市场搜索remote-ssh安装即可

如果使用的是wsl2,那会更加方便,进入编写k6脚本的路径下,直接输入

code .

即可在宿主机编写脚本。

测试条件

我这里要测试的对象,是一个在线考试系统,为了尽可能真实的模拟考试行为,我这里准备了几个接口,分别模拟了考试信息加载,身份验证,保存试卷草稿3个使用频率高的接口。

这里我就放一个最主要的,模拟用户保存草稿的接口

/// <summary>
/// 模拟保存草稿
/// </summary>
/// <param name="answer">提交一个长字符传</param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> SaveDraft(SimulateSaveDto dto)
{//模拟验证header的耗时await Task.Delay(new Random().Next(10, 300));int rd = new Random().Next(0, 100);var randomOne = (await _simulation1Repo.getListAsync(u => u.Id > 0))[rd];dto.sid=randomOne.Id;dto.answer = Utils.GenerateRandomCodeFast(new Random().Next(2, 8000));if (dto.answer.Length > CapConsts.CapMsgMaxLength){await _redisCachingProvider.StringSetAsync("tmpSimulate" + dto.sid, dto.answer, TimeSpan.FromMinutes(1));dto.answer = "";}await _capPublisher.PublishAsync(CapConsts.ClientPrefix + "SimulateSaveDraft", dto);Logger.Warning($"{DateTime.Now}:发布事务---模拟提交答案");return Json(_resp.success(dto.sid));
}

简单解释下这段代码,前半部分就是模拟构造了一个包含大字段的参数,因为用户提交的草稿可能会很大,我们目前的业务,光单选题就有100道,题目的id类型都是雪花算法生成的id,所以拼接完也是一个很大的字符,如果包含主观题,就更大了。

这里其实可以增量保存,但因为有其他业务关联,而且增量提交也有问题,比如用户第一份草稿提交的1-10题,到第三份草稿提交的25-30题,第四份又回去改动了第1题或者前面的题,这样又引入了新的复杂逻辑,所以这部分不多说,暂时就是这样全量保存草稿的场景。

后半部分是我使用消息队列的方式,把保存草稿的动作提交到队列里,这里在提交队列的时候做了一个前置处理,就是当答案的字符过长,就把答案暂存到Redis里,保证队列里传输的消息都不大。

一个小坑

之所以这样做,也是压测环节中发现的,因为我是使用PostgreSql来持久化存储的队列消息,EventBus组件用的CAP,当CAP在Pg里创建对列表的时候,会创建对应的索引,而当队列传输的消息过大,会报一个索引超长的错误,当然存储改为SQL Server或者手动把索引删掉就不会有这个问题,但为了确保更高的可用性,还是选择了规避。

事实上,正式接口里这里是采用的分段保存,思路就是分解答案,当字符串长度超过设定的最大长度,我们可以把字符串转成char数组,然后利用linq里对操作数组的chunk方法,分段保存用户答案,就可以避免这个问题了,也不用担心大字段临时存在Redis造成的性能问题,这篇的要点不在这里,就不细聊了。

测试脚本

测试脚本其实写完了回去看,还是挺简单的,但磨人的地方主要是在调整参数的过程,我们要根据系统的实际情况,编写压测的递进参数,尽可能的贴近实际情况,该快的时候快,该慢的时候慢,请求密度要尽可能的大,等等。

好了,直接看下这个脚本吧

import http from 'k6/http';
import { check, sleep } from 'k6';export const options = {thresholds: {checks: ['rate>0.95'],  // 至少 95% 的请求必须成功http_req_duration: ['p(95)<500']  // 95% 的请求响应时间小于 500 毫秒}// 设置并发用户数,stages: [{ duration: '10s', target: 10 }, // 起始阶段,10个线程运行30秒{ duration: '30s', target: 100 }, // 在接下来的30秒内将线程数增加到100{ duration: '30s', target: 300 }, // 再接下来的30秒内将线程数增加到300{ duration: '30s', target: 500 }, // 再接下来的30秒内将线程数增加到500{ duration: '30s', target: 800 }, // 再接下来的30秒内将线程数增加到800{ duration: '60s', target: 1000 }, // 再接下来的60秒内将线程数增加到1000{ duration: '120s', target: 1000 } // 保持1000个程运行120秒],
}export default function () {const url = '压测接口';let params = {headers: {'Content-Type': 'application/json'}};let payLoad ={answer:"[]",}let res = http.post(url,payLoad, params);// 解析响应体let response = JSON.parse(res.body);// 定义检查点let checks = {'status code is 200': (r) => r.status === 200,'API code is 0': (r) => response.code === 0};// 执行检查点check(res, checks);// 记录非成功的响应if (response.code !== 0) {console.log(response);//console.log(`Error: code=${response.code}, msg=${response.msg}, data=${JSON.stringify(response.data)}`);}sleep(2)}

控制台打印出来的结果

事实上,控制台打印的这些数据已经足够我们分析问题了,如果我们想更直观的观看压测过程的数据情况,可以开启webdashboard

K6_WEB_DASHBOARD=true k6 run simulatescript.js 

压测时,被测系统打印的日志

在这里插入图片描述

这样最后生成的报告会像这样👇

最后,其实不论是任何一种压测工具给出的报告,大家其实都不用有什么心智负担,因为现在是AI的时代,当我们想深入了解报告中所有参数的含义时,可以把报告直接扔给大模型,让大模型帮我们解读,这样我们也不用担心我们辛苦写的报告领导看不懂,当然我们自己也能起到促进作用,毕竟谁也不想完全被大模型替代,还是要有自己的见解才好。

好了,基本就这些内容了,下篇再细聊聊系统性能优化过程遇到的问题。

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

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

相关文章

气膜建筑:打造全天候安全作业空间,提升工程建设效率—轻空间

在现代建筑工程中&#xff0c;施工环境的管理和作业效率是决定项目进度和质量的关键因素。然而&#xff0c;施工过程中常常会受到天气变化的影响&#xff0c;诸如大风、雨雪、沙尘等恶劣天气常常延误工期&#xff0c;增加施工难度。为了解决这一问题&#xff0c;气膜建筑以其独…

CTF-Hub SQL 报错注入(纯手动注入)

​ 当输入1时&#xff0c;发现只有查询正确&#xff0c;基本上可以判断出没有回显 开始注入(工具hackerBar) 题目是报错注入&#xff0c;方向就比较明显&#xff0c;大致说一下用到的函数和原理。 常见报错注入函数&#xff1a; 通过 floor() 报错注入通过 extractValue() …

HCIE:详解OSPF,从基础到高级特性再到深入研究

目录 前言 一、OSPF协议基本原理 简介 基本原理 OSPF路由器类型 OSPF网络类型 OSPF报文类型和封装 OSPF邻居的建立的维护 DR和BDR的选举 伪节点 LSDB的更新 OSPF的配置 二、OSPF的高级特性 虚连接&#xff08;Virtual-Link&#xff09; OSPF的LSA和路由选择 OSPF…

C++游戏开发入门:如何从零开始实现自己的游戏项目?

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C游戏开发的相关内容&#xff01; 关于【…

直接抄作业!Air780E模组LuatOS开发:位运算(bit)示例

在嵌入式开发中&#xff0c;位运算是一种高效且常用的操作技巧。本文将介绍如何使用Air780E模组和LuatOS进行位运算&#xff0c;并通过示例代码帮助读者快速上手。 一、位运算概述 位运算是一种在计算机系统中对二进制数位进行操作的运算。由于计算机内部数据的存储和处理都是…

linux centos nginx编译安装

编译安装nginx&#xff08;Centos&#xff09; 编译需要的基础环境yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c1.下载nginx源码包 Nginx源码包下载地址&#xff1a;nginx源码包下载 2. 上传nginx源码包到服务器 我上传的地址是/home/chenhao/nginx…

公链开发中的技术实现路径:构建高效、安全的去中心化网络

区块链技术作为数字经济的重要组成部分&#xff0c;公链&#xff08;Public Chain&#xff09;是其核心架构之一。公链作为去中心化的数字账本&#xff0c;不仅承载着去中心化应用&#xff08;DApp&#xff09;的运行&#xff0c;还确保了交易的透明、安全性。随着区块链技术的…

TortoiseGit 将本地已有仓库推送到远程

TortoiseGit 将本地已有仓库推送到远程 一、创建线上仓库二、创建本地仓库三、提交内容到本地仓库四、添加远程仓库地址补充 一、创建线上仓库 在gitlab管理面页面按这前讲过的步骤创建一个空仓库。&#xff08;通常我们把服务器上这个仓库叫远程仓库&#xff0c;把我们自己电…

3.22【机器学习】决策树作业代码实现

4.1由于决策树只在样本同属于一类或者所有特征值都用完或缺失时生成叶节点&#xff0c;同一节点的样本&#xff0c;在路径上的特征值都相同&#xff0c;而训练集中又没有冲突数据&#xff0c;所以必定存在训练误差为0的决策树 4.2使用最小训练误差会导致过拟合&#xff0c;使得…

C语言:C语言实现对MySQL数据库表增删改查功能

基础DOME可以用于学习借鉴&#xff1b; 具体代码 #include <stdio.h> #include <mysql.h> // mysql 文件&#xff0c;如果配置ok就可以直接包含这个文件//宏定义 连接MySQL必要参数 #define SERVER "localhost" //或 127.0.0.1 #define USER "roo…

Spark基本命令详解

文章目录 Spark基本命令详解一、引言二、Spark Core 基本命令1、Transformations&#xff08;转换操作&#xff09;1.1、groupBy(func)1.2、filter(func) 2、Actions&#xff08;动作操作&#xff09;2.1、distinct([numTasks])2.2、sortBy(func, [ascending], [numTasks]) 三、…

github webhooks 实现网站自动更新

本文目录 Github Webhooks 介绍Webhooks 工作原理配置与验证应用云服务器通过 Webhook 自动部署网站实现复制私钥编写 webhook 接口Github 仓库配置 webhook以服务的形式运行 app.py Github Webhooks 介绍 Webhooks是GitHub提供的一种通知方式&#xff0c;当GitHub上发生特定事…

蓝桥杯模拟题不知名题目

题目:p是一个质数&#xff0c;但p是n的约数。将p称为是n的质因数。求2024最大质因数。 #include<iostream> #include<algorithm> using namespace std; bool fun(int x) {for(int i 2 ; i * i < x ; i){if(x % i 0)return false;}return true; } int main() …

【从零开始的LeetCode-算法】3264. K 次乘运算后的最终数组 I

给你一个整数数组 nums &#xff0c;一个整数 k 和一个整数 multiplier 。 你需要对 nums 执行 k 次操作&#xff0c;每次操作中&#xff1a; 找到 nums 中的 最小 值 x &#xff0c;如果存在多个最小值&#xff0c;选择最 前面 的一个。将 x 替换为 x * multiplier 。 请你…

Python 爬虫指定数据提取【Xpath】

Xpath 是一个非常好用的解析方法&#xff0c;使用前需要安装对应的库&#xff0c;这个自行搜索&#xff0c;很简单&#xff01; 示例代码 from lxml import etree text <div><ul><li class"item-0"><a href"link1.html">first …

C++设计模式(观察者模式)

一、介绍 1.动机 在软件构建过程中&#xff0c;我们需要为某些对象建立一种“通知依赖关系”&#xff0c;即一个对象的状态发生改变&#xff0c;所有的依赖对象&#xff08;观察者对象&#xff09;都将得到通知。如果这样的依赖关系过于紧密&#xff0c;将使软件不能很好地抵…

排序算法2

排序算法1-CSDN博客 排序算法1中提及的是较为基础(暴力实现&#xff0c;复杂度较高)的排序算法&#xff0c;不适合于数据量较大的场景&#xff0c;比如序列长度达到1e5 接下来以蓝桥另一道题目来理解其它的排序算法 蓝桥3226 蓝桥账户中心 样例 5 1 5 9 3 7 4、快速排序 快速排…

go结构体匿名“继承“方法冲突时继承优先顺序

在 Go 语言中&#xff0c;匿名字段&#xff08;也称为嵌入字段&#xff09;可以用来实现继承的效果。当你在一个结构体中匿名嵌入另一个结构体时&#xff0c;嵌入结构体的方法会被提升到外部结构体中。这意味着你可以直接通过外部结构体调用嵌入结构体的方法。 如果多个嵌入结…

Ubuntu Server 22.04.5 从零到一:详尽安装部署指南

文章目录 Ubuntu Server 22.04.5 从零到一&#xff1a;详尽安装部署指南一、部署环境二、安装系统2.1 安装2.1.1 选择安装方式2.1.2 选择语言2.1.3 选择不更新2.1.4 选择键盘标准2.1.5 选择安装版本2.1.6 设置网卡2.1.7 配置代理2.1.8 设置镜像源2.1.9 选择装系统的硬盘2.1.10 …

鸿蒙征文|鸿蒙技术分享:使用到的开发框架和技术概览

目录 每日一句正能量前言正文1. 开发环境搭建关键技术&#xff1a;2. 用户界面开发关键技术&#xff1a;3. 应用逻辑开发关键技术&#xff1a;4. 应用测试关键技术&#xff1a;5. 应用签名和打包关键技术&#xff1a;6. 上架流程关键技术&#xff1a;7. 后续维护和更新关键技术…