Published on

k6 负载测试全面指南:从脚本编写到结果可视化

Authors
  • avatar
    Name
    Liant
    Twitter

k6 简述

k6脚本生命周期

地址:https://k6.io/docs/using-k6/test-life-cycle/

有4个不同的阶段

  1. 初始化
  2. 设置
  3. VU 代码
  4. 拆解
img_2.png

1、K6的功能

请求方式

k6请求方式地址:https://k6.io/docs/javascript-api/k6-http/

get
    {run_k6}
    http.get('url');
post
{run_k6_post}
http.post(url, payload, params);
payload:参数
params:请求头
const params = {
        headers: {
            'Content-Type': 'application/json',
            'X-Client-Id': client_id,
            'X-Timestamp':timestr,
            'X-Random':randomint,
            'X-Signature':sign
        },
      };
批处理
{run_k6_batch}
方式:
1、请求参数为对象
2、请求参数为对象,且具有命名属性
3、请求参数为数组
4、请求参数为URL 字符串的数组

一起请求时,请求url顺序不固定

指标

指标地址:https://k6.io/docs/using-k6/metrics/

内置指标
vus:当前活动虚拟用户数
vus_max:最大可能数量的虚拟用户
iterations:虚拟用户执行 JS 脚本的总次数
iteration_duration:完成一次完整请求所花费的时间
dropped_iterations:由于缺少 VU(对于到达率执行程序)或缺少时间(在基于迭代的执行程序中已过期的 maxDuration)而未启动的迭代次数
    解释:设置了iterations,maxDuration就可能出现这种情况;例:总次数为10000,最大持续时间为:为5s
data_received:接收的数据
data_sent:发送的数据量
checks:成功率
特定于 HTTP 的内置指标
仅当测试发出 HTTP 请求时,才会生成这些指标
http_reqs:生成的 HTTP 请求总数
http_req_blocked:在发起请求之前等待的时间
http_req_connecting:建立到远程主机的TCP连接所花费的时间
http_req_tls_handshaking:与远程主机握手TLS会话所花费的时间
http_req_sending:向远程主机发送数据所花费的时间
http_req_waiting:等待远程主机响应所花费的时间
http_req_receiving:从远程主机接收响应数据所花费的时间
http_req_duration:远程服务器处理请求和响应需要多长时间,不包含初始的DNS查找/连接时间
    http_req_duration = http_req_sending+http_req_waiting+http_req_receiving
http_req_failed:请求失败率,响应status code不为200-400之间
指标类型
Counter:求和
Gauge:展示添加的数据最小值,最大值
Rate:展示百分比
Trend:展示最小值、最大值、平均值,百分位数,90%的值,95%的值
自定义指标
{run_k6_batch}
1、引入依赖
2、声明自定义指标类型
3、将数据添加到自定义指标
检查
检查是测试运行时值的真/假条件
{run_k6_check}
1、系统以 200 状态响应
2、响应正文包含某些文本
3、响应正文具有指定的大小
检查失败正常情况下不会使测试失败,只会增加检查失败率,如果要使测试失败,需要添加阈值
    {run_k6_check_thresholds}
    方式一:根据所有检查结果判断
    export const options = {
        vus: 2,
        duration: '2s',
        thresholds: {
            checks: ['rate>0.9'], //检查成功率大于0.9,否,终止测试
        },
    };
    方式二:根据标签判断  {run_k6_check_thresholds_too}
    export const options = {
        vus: 2,
        duration: '2s',
        thresholds: {
            'checks{mytag:mytag}': ['rate>0.9'], //检查成功率大于0.9,否,终止测试
        },
    };
阈值
阈值是测试指标的通过/失败条件
阈值类型是根据指标类型添加
    1、Counter:计数器,用于数值累计求和后的判断
        例如:响应时间<1s
    2、Gauge:轨距,用于固定值判断
        例如:接口响应大小<400字节
    3、Rate:率,用于固定百分比判断
        例如:错误率<99%
    4、Trend:趋势,用于平均值,最大值,最小值,百分90等值的判断
    5、添加check的阈值
    6、添加标签子指标
格式:
{run_k6_thresholds}
export const options = {
    vus: 3,
    duration: '10s',
    thresholds: {
        checks: ['rate>0.9'], //检查成功率大于0.9
        time: ['avg<200'], //平均时间的接口运行时间小于500ms
        s_rate: ['rate>0.95'], //响应状态码为200的请求需大于95%
        ContentSize: ['value<1000'],//接口响应体大小需小于1000字节
        err: ['count<5'], // 错误量需小于5
        'http_req_waiting{type: tag_value}': ['p(95)>200'],//标签为type: tag_value 的95%的等待时间大于200MS
    },
};
options 选项

参考地址:https://k6.io/docs/using-k6/k6-options/reference/

优先级:
    命令行>环境变量>脚本设置>配置文件>默认值
{run_k6_options}
discardResponseBodies: true  --不返回请求的响应结果
    {run_k6_api}
    设置为true时,可在单个http请求后面,加 { responseType: 'text' }
    const res = http.post(url, body,{ responseType: 'text' });

场景

执行固定的请求数量---shared-iterations
{run_k6_scene}
总请求数量 = iterations
scenarios: {
    contacts: { //方案名,也可以是标签名
        executor: 'shared-iterations',
        vus: 10,
        iterations: 200,
        maxDuration: '30s',
        },
    },
每个虚拟用户固定请求次数---per-vu-iterations
{run_k6_scene_1}
总请求次数= uv * iterations
scenarios: {
    contacts: {
        executor: 'per-vu-iterations',
        vus: 10,
        iterations: 200,
        maxDuration: '30s',
    },
},
固定虚拟用户数,执行固定时间---constant-vus
{run_k6_scene_1}
html: {
        executor: 'constant-vus',
        vus: 10,
        duration: '4m',
    }
在固定时间段增加或减少虚拟用户数---ramping-vus
scenarios: {
    contacts: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [ // 阶段,必传;0-20S内虚拟用户数增加到20,20s-30s虚拟用户数减少到0
        { duration: '20s', target: 10 },
        { duration: '10s', target: 0 },
      ],
      gracefulRampDown: '0s',//到达最大持续时间,已经发起请求的数据,可停止时间
    },
  },
在某一秒发起固定的请求---constant-arrival-rate(类似集合点)
scenarios: {  //每一秒运行30次脚本,持续时间为30s
    contacts: {
      executor: 'constant-arrival-rate',
      duration: '30s',
      rate: 30,
      timeUnit: '1s',// 非必填
      preAllocatedVUs: 2,
      maxVUs: 50,//非必填
    },
  },
在某一秒发起固定的请求---ramping-arrival-rate(类似集合点)
  scenarios: { // 在某一个时间段,以每秒30次的迭代增加到目标值
    contacts: {
      executor: 'ramping-arrival-rate',
      startRate: 300,
      rate: 30,//非必填
      timeUnit: '1s',//非必填
      preAllocatedVUs: 2,
      maxVUs: 50,//非必填
      stages: [
        { target: 300, duration: '1m' },
        { target: 600, duration: '2m' },
        { target: 600, duration: '4m' },
        { target: 60, duration: '2m' },
      ],
        },
    },
限制最大用户数 -----externally-controlled
scenarios: {
    contacts: {
      executor: 'externally-controlled',
      vus: 10,
      maxVUs: 50,
      duration: '10m',
    },
  },

报告

官网报告

  1. 在官网注册账号
  2. 在个人信息,点击API token
  3. 复制个人API token
  4. 在本地命令行登录账号 k6 login cloud --token 5a774f670ac
  5. 运行脚本 添加 --out cloud : k6 run --out cloud .\run_files\run_k6_api.js

控制台会展示报告地址:https://app.k6.io/runs/1454742

本地生成HTML报告

  1. 下载文件到本地:https://github.com/benc-uk/k6-reporter
  2. 脚本新增
    import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
    import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js";
    
    export function handleSummary(data) {
      return {
        "result.html": htmlReport(data),
        stdout: textSummary(data, { indent: " ", enableColors: true }),
      };
    }
    

Grafana

地址:https://k6.io/docs/results-visualization/influxdb-+-grafana/

    k6 run .\run_files\run_k6_high_api.js --out influxdb=http://172.16.5.110:8086/k6

运行命令

    k6 run XXX.js

运行结果

img.png

增加虚拟用户数(VU),脚本持续运行时间(s)

命令行的方式
    -- vus X --duration X(s)
    - 为中文段横杆
    k6 run --vus 10 --duration 2s .\run_files\run_k6.js
代码添加方式
export const options = {
  vus: 10,
  duration: '30s',
};
 k6 run .\run_files\run_k6_vus_duration.js
img_1.png
实现梯步增加虚拟用户数
场景是:0-30s用户数增加到20,30s-2m用户数减少到10,2m-2m20s用户数减少到0
    30S用户数增加到20个,1m30s用户数减少到10,20s用户数减少到0
export const options = {
  stages: [
    { duration: '30s', target: 20 },
    { duration: '1m30s', target: 10 },
    { duration: '20s', target: 0 },
  ],
};