K6负载测试工具深入

2022-06-17 08:55:21 浏览数 (1)

前言

前面我已经出了一篇 K6负载测试工具初探的文章,今天我们继续来深入了解 K6 的高级用法。

忽略 https 证书

想信很多同学都遇到了这个问题,当我们的服务协议是 https 时,直接使用示例中的代码会报错缺少证书。但是对于我们测试来说,我们通常会使用忽略证书的方式,requests 是可以在发送请求中增加 verify=False 来实现。那 k6 如何实现呢?

我们可以在测试脚本中增加自定义的配置来开启 https 证书忽略。

代码语言:javascript复制
import http from 'k6/http';

// k6配置
export const options = {
    // 忽略https证书
    insecureSkipTLSVerify: true,
  };

// setup
// 这就就是你的代码了

setup 和 teardown

从官方文档,我们可以得知 K6 是原生支持 setupteardown 的,我们只需要在测试脚本中定义这两个方法即可。

代码结构:

代码语言:javascript复制
import http from 'k6/http';

// 这里就是setup
export function setup() {
  const res = http.get('https://httpbin.org/get');
  return { data: res.json() };
}

// 这里是你的测试代码
export function teardown(data) {
  console.log(JSON.stringify(data));
}

// 这里就是teardown
export default function (data) {
  console.log(JSON.stringify(data));
}

断言

对于性能测试,我们也需要对测试结果进行断言,K6 提供了断言方法 check,你可以使用它自定义断言规则。

代码语言:javascript复制
// code
export default function () {
    const url = 'http://test.test.com:3456/v2.1/server/detail?serverId=serverId';
    const params = {
        headers: {
            'Content-Type': 'application/json'
        },
    };
    let res=http.get(url, params);

    // 断言
    check(res, {
        'response code was 200': (res) => res.status == 200,
      });
}

如上,我们可以使用 response 对象中的多个属性进行断言。

自定义失败信息:

代码语言:javascript复制
import http from 'k6/http';
import { check, fail } from 'k6';

export default function () {
  const res = http.get('http://httpbin.org');
  const checkOutput = check(
    res,
    {
      'response code was 200': (res) => res.status == 200,
      'body size was 1234 bytes': (res) => res.body.length == 1234,
    },
    { myTag: "I'm a tag" }
  );

  if (!checkOutput) {
    fail('unexpected response');
  }
}

参数传递(接口统一鉴权)

在测试需要鉴权的接口时,我们通常要在 setup 中获取 token,然后供后面的测试使用,K6 也原生支持,因为 K6 的测试脚本是使用 JavaScript 写的,所以我们只需要在 setup 中获取到 token,然后将其 return 出来即可。

这样我们就可以解决接口需要鉴权的问题了。

示例代码:

代码语言:javascript复制
import http from 'k6/http';
import { check } from 'k6';

// k6配置
export const options = {
    // 忽略https证书
    insecureSkipTLSVerify: true,
  };

// setup
export function setup() {
    console.log('[SETUP]: 开始初始化!');
    const url = 'https://test.test.com:5000/v3/auth/tokens';
    const payload = JSON.stringify(
        {
            "auth": {
                "identity": {
                    "methods": [
                        "password"
                    ],
                    "password": {
                        "user": {
                            "name": 'admin',
                            "domain": {
                                "name": "default"
                            },
                            "password": 'pwd@pwd'
                        }
                    }
                },
                "scope": {
                    "project": {
                        "domain": {
                            "id": "default"
                        },
                        "name": "admin"
                    }
                }
            }
        }
    );

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

    let response=http.post(url, payload, params);
    const tk = (response.headers)['X-Subject-Token'];
    console.log('[SETUP]: 完成初始化!');
    console.log(tk)
    // 将token返回出去
    return tk;
}

// code
// 将前面的tk接收
export default function (tk) {
    const url = 'http://test.test.com:3456/v2.1/server/detail?serverId=serverId';
    // console.log(tk);
    const params = {
        headers: {
            'Content-Type': 'application/json',
            // 在这里传入tk,用于鉴权
            'x-auth-token': tk,
            'userName': 'admin',
            'userId': 'userId',
            'projectId': 'projectId'
        },
    };
    // console.log((params.headers)['x-auth-token']);
    let res=http.get(url, params);
    // console.log(res.body);

    // 断言
    check(res, {
        'response code was 200': (res) => res.status == 200,
      });
}

// teardown
export  function teardown() {

    console.log('[TEARDOWN]: 测试结束!');
}

以上就是完整的对于 https 服务的测试,其包含 setupteardown 过程,也对测试结果进行了断言。

并发实践

以上的示例是固定的 UV 对单个接口进行的压测,当我们需要模拟实际场景的时候,往往是很多 UV 对多个接口进行访问的。对于这种场景 K6 也提供了 batch 方法,可以实现对多个请求进行并发测试。

第一种写法

代码语言:javascript复制
// code
export default function () {

    // batch 第一种写法
    let res=http.batch([
        ['GET','https://httpbin.org/get',null,{headers:{'Content-Type': 'application/x-www-form-urlencoded'}}],
        ['POST','https://httpbin.org/post',{hello: 'world!'},{headers:{'Content-Type': 'application/x-www-form-urlencoded'}}]
    ]);
    // 断言1
    check(res[0], {
        'response code was 200': (res) => res.status == 200,
      });

第二种写法

代码语言:javascript复制
// code
export default function () {
    // batch 第二种写法
    let req1 = {
        method: 'GET',
        url: 'https://httpbin.org/get',
     };
    let req2 = {
        method: 'POST',
        url: 'https://httpbin.org/post',
        body: {hello: 'world!',},
        params: {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        },
    };
    let res = http.batch([req1, req2]);
    // 断言2
    check(res[0], {
        'response code was 200': (res) => res.status == 200,
      });
}

实际上,这两种写法的区别就是请求的组装在何处,第一种写法的组装在 batch 内,第二种写法单独组装,然后将请求对象传入 batch

测试结果的分析和普通场景同理。

并发权重问题

前面我们已经实现了模拟多个接口的并发,但实际使用中,接口的使用频率是不一样的,所以我们需要能够配置接口的权重。但是我没找到 K6 如何定义接口权重。

0 人点赞