压测工具 K6 的使用笔记

k6 是最近发现比较有趣的压测工具,它是通过 JS 创建测试脚本的,这方面跟 Gatling 类似,不过 Gatling 使用 Scala 创建测试脚本。 k6 底层的执行引擎是使用 Go 开发的,内嵌了 JavaScript 运行时,所以可以使用 JS 创建测试脚本,而且使用 JS 作为测试脚本语言也是明智的选择,因为 JS 真的非常的流行,更加具有普适性。

k6 压测工具比 JMeter 压测工具更轻量化,占用更少的资源,性能更好些。

安装

由于笔者使用 Win 11 操作系统,而且 Win 11 操作系统内置了 winget 安装工具,所以笔者直接使用 winget 安装 k6:

winget install k6

其他的安装方式可以参考安装文档

k6 的使用

k6 的 Hello World

k6 有一个测试页面,但是国内访问比较慢,若对测试脚本编写有疑惑的可以参考一下测试页面的案例。

学习编程从 Hello World 开始,创建一个测试脚本hello-world.js

import http from 'k6/http';
import { sleep } from 'k6';

export default function () {
  http.get('https://www.baidu.com/');
  // sleep() 函数作为多个串联请求的思考时间
  sleep(1);
}

default function 就相当于 Java 的 Main 方法,是程序的入口。

默认参数运行:

# 默认参数是每个 URL 1 个虚拟用户访问一次 
k6 run hello-world.js

模拟 10 个虚拟用户(VU),连续压测 30 秒:

k6 run --vus 10 --duration 30s hello-world.js

也可以把这些参数写到脚本里(效果和上面命令行一样):

import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
  vus: 10,
  duration: '30s',
};
export default function () {
  http.get('https://www.baidu.com/');
  sleep(1);
}

k6 压测结果数据解读

下面的测试结果是运行上述 hello-world.js测试脚本所得的,测试结果由多个数据汇总而成,下面解读一下各个数据表示什么意思。

  • scenarios:简述测试脚本运行的情况;说明有多少个测试案例、最大的虚拟用户数,最大的运行持续时间。
  • data_received:接收到的数据量大小
  • data_sent:发送的数据量大小
  • http_req_blocked:在发起请求之前被阻塞的时间
  • http_req_connecting:建立到远程主机的 TCP 连接所花费的时间
  • http_req_duration:请求的总时间。它等于 http_req_sending + http_req_waiting + http_req_receiving重要指标
  • http_req_failed:失败请求率
  • http_req_receiving:从远程主机接收响应数据所花费的时间,而没有初始DNS查找/连接时间
  • http_req_sending:将数据发送到远程主机所花费的时间
  • http_req_tls_handshaking:与远程主机握手建立TLS会话所花费的时间
  • http_req_waiting:等待远程主机响应所花费的时间
  • http_reqs:总请求数量TPS
  • iteration_duration:完成默认/主函数的一次完整迭代所花费的时间
  • iterations:脚本中的函数被执行的次数
  • vus:当前活动的虚拟用户数
  • vus_max:虚拟用户的最大数量
  • checks:checks 项的成功率

HTTP Requests

Get 请求

Get 请求的语法是get(url,[params])

import http from 'k6/http';
export let options = {
  vus: 100, // 指定要同时运行的虚拟用户数量
  duration: '10s', // 指定测试运行的总持续时间
};
// default 默认函数
export default function () {
  // 通过 params 设置标头
  let params = { headers: { 'Content-Type': 'application/json' } };
 
  var res=http.get("https://test.k6.io",params)
}

Post 请求

Post 请求的语法是post(url,[body],[params]

import http from 'k6/http';

// 加载本地的文件数据,通过文件数据可以构建动态参数请求了;download the data file here: https://test.k6.io/static/examples/users.json
// 加载的数据不能直接传输给后端,传输给后端需要使用 JSON.stringify() 转换一下
// 若是直接传输给后端就不需要转换成 JSON,也就是省略 JSON.parse() 这部调用
const loginData = JSON.parse(open("./users.json"));

export default function () {
  const url = 'http://test.k6.io/login';
  // Using a JSON string as body
  const payload = JSON.stringify({
    email: 'aaa',
    password: 'bbb',
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
  };

  http.post(url, payload, params);
}

通用 Request

通用 Request 的语法是request(method,url,[body],[params])

import http from 'k6/http';

const url = 'https://httpbin.test.k6.io/post';

export default function () {
  const data = { name: 'Bert' };

  // Using a JSON string as body
  let res = http.request('POST', url, JSON.stringify(data), {
    headers: { 'Content-Type': 'application/json' },
  });
  console.log(res.json().json.name); // Bert

  // Using an object as body, the headers will automatically include
  // 'Content-Type: application/x-www-form-urlencoded'.
  res = http.request('POST', url, data);
  console.log(res.json().form.name); // Bert
}

关于 HTTP Requests 更多的请求处理方式请参考HTTP Requests 文档

响应结果断言

一个请求是否正确,需要根据返回结果进行判断,判断请求返回结果一般是使用断言的。k6 必然也是提供响应结果断言检查的,但断言失败不会导致测试中止或以失败状态结束。相反,k6 在测试继续运行时跟踪失败检查的比率。

响应结果结构体可以参考文档Response

检查 HTTP 响应代码

检查非常适合编码与 HTTP 请求和响应相关的断言。例如,此代码段确保 HTTP 响应代码为 200:

import { check } from 'k6';
import http from 'k6/http';

export default function () {
  const res = http.get('http://test.k6.io/');
  check(res, {
    'is status 200': (r) => r.status === 200,
  });
}

当脚本包含检查时,摘要报告会显示通过了多少测试检查:

k6 run script.js

  ...
    ✓ is status 200

  ...
  checks.........................: 100.00% ✓ 1        ✗ 0
  data_received..................: 11 kB   12 kB/s

在此示例中,请注意检查“状态为 200”的调用成功率为 100%。

检查响应正文中的文本

有时,即使是 HTTP 200 响应也包含错误消息。在这些情况下,考虑添加一个检查来验证响应主体,如下所示:

import { check } from 'k6';
import http from 'k6/http';

export default function () {
  const res = http.get('http://test.k6.io/');
  check(res, {
    'verify homepage text': (r) =>
      r.body.includes('Collection of simple web-pages suitable for load testing'),
  });
}

若请求结果以 JSON 格式返回,我们可以校验 JSON 对象的:

import { check } from 'k6';
import http from 'k6/http';

export default function () {
  const res = http.get('http://test.k6.io/');
  /*
  	{
      "status":1,
      "code":"SYS_OK",
      "message":"请求成功!",
      "data":[]
		}
    例如请求返回值是上面的 JSON 对象,所以需要判断 status 字段才能判断请求是否成功。
  */
  // res.json([select]) 可以将响应结果转换为 JSON 对象或 JSON 数组,
  //   通过可选参数 select 获取某个字段值的
  check(res, {
    'status was 200': (r) => r.status == 200,
    'business status was 0': (r) => r.json("status") == 0
  });
}

res.json([select])函数的更多内容可以参考Response.json( [selector] )

检查响应主体大小

要验证响应主体的大小,您可以使用如下检查:

import { check } from 'k6';
import http from 'k6/http';

export default function () {
  const res = http.get('http://test.k6.io/');
  check(res, {
    'body size is 11,105 bytes': (r) => r.body.length == 11105,
  });
}

添加多项检查

您还可以在单个check()语句中添加多个检查:

import { check } from 'k6';
import http from 'k6/http';

export default function () {
  const res = http.get('http://test.k6.io/');
  check(res, {
    'is status 200': (r) => r.status === 200,
    'body size is 11,105 bytes': (r) => r.body.length == 11105,
  });
}

执行此测试时,输出将如下所示:

k6 run checks.js

  ...
    ✓ is status 200
    ✓ body size is 11,105 bytes

  ...
  checks.........................: 100.00% ✓ 2        ✗ 0
  data_received..................: 11 kB   20 kB/s

Option 选项

虚拟用户

Vus:指定要同时运行的虚拟用户数量,必须是一个整数,和 duration 搭配使用。默认值:1

export let options = {
  vus: 10,
  duration: '10s',
};
k6 run -u 10 test.js
k6 run --vus 10 test.js

持续时间

Duration:一个字符串,指定测试运行的总持续时间,与 vus 选项一起使用。默认值:null

export let options = {
  vus: 10,
  duration: '10s',
};
k6 run -u 10 --d 20s  test.js
k6 run --vus 10 --duration 20s  test.js

模拟多阶段

RPS:每秒发出的最大请求数, 默认值:0;k6 压测默认是并发模式,配置了 RPS 应该调整为吞吐量模式,限定压测的 RPS。

不推荐使用这个选项,因为它有可能不正确;例如,在云端或分布式执行中,此选项独立影响每个 k6 实例。也就是说,它不像 VU 那样被分片。我们强烈建议到达率执行器模拟恒定 RPS,而不是这个选项。

export let options = {
  rps: 500,
};

模拟多测试阶段

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 20 },
    { duration: '1m30s', target: 10 },
    { duration: '20s', target: 0 },
  ],
};

export default function () {
  const res = http.get('https://www.baidu.com/');
  check(res, { 'status was 200': (r) => r.status == 200 });
  sleep(1);
}

前 30 秒,用户从 0 增涨到 20。然后接下来的 1 分 30 秒,持续模拟 10 个用户。然后用 20 秒的时间,把并发用户数从 10 减少到 0。

趋势汇总统计

k6 默认的趋势汇总统计格式是:avg,min,med,max,p(90),p(95),我们可以自定义趋势汇总统计,例如我们需要关注p(99)这个指标,那么我们可以自定义summaryTrendStats的值:

# 添加 p(99) 指标
export const options = {
    summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(90)','p(95)', 'p(99)']
  }

日志输出

输出到控制台:

import http from 'k6/http';
export let options = {
  vus: 10,
  duration: '2s',
};

export default function () {
  let res = http.get('http://www.baidu.com');
   console.log('log')
   console.info('info');
   console.error('err');
   console.debug('debug')
   console.warn('warn')
}

输出到文件,输出到文件的同时控制台不再输出:

k6 run test.js --console-output=test.log

k6 脚本的调试

在使用 k6 的时候遇到了一个问题,请求后端接口的时候报 JSON 相关的错误,突然想到该如何调试 K6 的脚本呢,经过查询发现 k6 的脚本不能很好的支持调试,因为 k6 的底层是基于 Go 而不是 Node.js 的,k6 只是使用了 Javascript 脚本作为测试内容的调试器而已。所以调试 k6 脚本比较有效的方式是实用console.log()函数了。若是想了解 HTTP API 接口的请求情况可以使用--http-debug参数,更多详细内容参考:HTTP debugging

k6 测试结果的可视化

Web dashboard

通过 web dashboard 我们可以在本地浏览器实时查看接口测试情况。

Web Dashboard 是 k6 的内置功能。你可以在运行测试脚本时通过设置K6_WEB_DASHBOARD环境变量来启用它true,例如:

k6  --out 'web-dashboard' run script.js

          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  /    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| __\ _____/ .io

     execution: local
        script: ../extensions/xk6-dashboard/script.js
 web dashboard: http://127.0.0.1:5665
        output: -

默认情况下,Web Dashboard 在 localhost 端口上可用。您可以使用仪表板选项5665更改主机和端口。

通过 k6 Cloud 进行可化

我们可以将本地的测试结果输出到 k6 Cloud,借助 k6 Cloud 生成优美的测试结果页面。

要使用 k6 Cloud 需要先注册app.k6.io,推荐直接用 Github 账号登录,研发人员肯定有 Github 账号吧。

使用 Github 登录的时候一直出错,所以笔者使用 Google 账号登录了。🙈

登录成功后,通过自己的账户获取 API Token

复制API token,然后在命令行运行:

k6 login cloud --token <YOUR_K6_CLOUD_API_TOKEN>

这样,你的客户端 k6 程序也知道了如何访问你的云端。

将运行测试脚本之后的结果上传到云端,生成更直观和更可读的测试结果;通过添加--out cloud-o cloud参数即可将测试结果上传到云端:

k6 run --out cloud hello-world.js 
或简写 
k6 run -o cloud hello-world.js

因为之前通过 API token,我们已经让本地程序绑定了云端。现在测试数据会实时发送到云端:

测试结果如下:

对于一次压力测试来说,其实最关心的就是红框里的这几个数据了。

还可以生成测试报告:

并且生成测试结果的 PDF 文件:

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

在这里插入图片描述

 ​​​​软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值