負載壓力測試工具 - K6

K6 是一套用 JavaScript 編寫測試腳本的工具,對於前端的開發夥伴可是相當的友善,Jetbrains IDE 也有整合它,在開發/測試體驗上肯定有一定的水準,為此深得我心,於是便快速的調查一番,紀錄使用心得

開發環境

  • Windows 11
  • Rider

安裝 K6

在作業系統安裝 k6

scoop

scoop install k6

winget

winget install k6

choco

需要管理員權限

choco install k6

 

在 powershell 執行 

k6 version

在 Rider 安裝 K6 外掛

k6 - IntelliJ IDEs Plugin | Marketplace (jetbrains.com)

運行 k6 腳本

接下來,快速的跑一個腳本試試

  1. 新增 1.js
  2. 設定 virtual users(簡稱VUs,虛擬使用者),k6 會幫你建立多個請求
  3. 增加測試時間 (duration)
  4. Ramp the number of reque

在 rider 新增一個 1.js 檔並複製以下內容

如果沒有 rider 也沒有關係,一般的文字編輯器搭配 powershell / cmd 也是可以的

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

export default function () {
 http.get('http://test.k6.io');
 sleep(1);
} 

 

 

 

 

在 Rider 編寫 js,執行測試(Ctrl+F5),都在同一個 IDE 裡面完成

沒有 Rider 的就在 powershell / cmd 執行

k6 run 1.js

 

增加更多的 VUs

k6 run --vus 10 --duration 30s script.js

 

使用參數 options 物件

可以在 test js 把 VUs、duration 寫在 options 物件,而不是每一次都在 cli 輸入--vus 10 --duration 30s

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

 

增加減少 VUs

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://httpbin.test.k6.io/');
 check(res, { 'status was 200': (r) => r.status == 200 });
 sleep(1);
}

 

Options

參數配置測試運行的行為,例如,配置測試的標籤、thresholds、user agents 及 virtual users和 iterations 的數量。

k6 提供幾種設參數配置的方式

  • CLI flags
  • 環境變數
  • js file 的 options object


優先順序

可以從下圖得知參數的覆蓋順序
 

Options passed as command-line flags override all other options: defaults < script options < environment variables < command-line flags

 

範例:options object 裡面配置測試參數

import http from 'k6/http';
export const options = {
 hosts: { 'test.k6.io': '1.2.3.4' },
 stages: [
   { duration: '1m', target: 10 },
   { duration: '1m', target: 20 },
   { duration: '1m', target: 0 },
 ],
 thresholds: { http_req_duration: ['avg<100', 'p(95)<200'] },
 noConnectionReuse: true,
 userAgent: 'MyK6UserAgentString/1.0',
};
export default function () {
 http.get('http://test.k6.io/');
}

 

範例:設定環境變數

PS C:\k6> $env:K6_NO_CONNECTION_REUSE=true; $env:K6_USER_AGENT="MyK6UserAgentString/1.0"; k6 run script.js
PS C:\k6> k6 run --no-connection-reuse --user-agent "MyK6UserAgentString/1.0" script.js

 

官網已經有很詳細的說明,這裡我就挑我認為重要的列出來

VUs:整數,指定要同時運行的 VU 數量,與 iterations 或 duration 一起使用。

Duration:字串,指定應運行測試運行的總持續時間。在此期間,每個 VU 都會循環執行。

Iterations:整數,指定要在測試運行中執行的默認函數的迭代總數。

RPR:每秒發出的最大請求數,所有 VU 的總數,但官方建議使用 arrival-rate executors  來模擬請求端的 RPS。

 

官方建議 RPS 控速採用 arrival-rate

參考 Arrival-rate VU allocation (k6.io)

rate:目標的 PRS 期望數字
duration:持續時間
preAllocatedVUs:每次執行增加 VUs 的數量
maxVUs:VUs 最大數 
timeUnit:多久時間達到 rate,如果場景有 rate: 10, timeUnit: '1m',k6 會嘗試每 6 秒開始一次新的迭代

範例如下

export const options = {
 // discardResponseBodies: true,
 scenarios: {
   contacts: {
     executor: 'constant-arrival-rate',
     duration: `5m`,
     rate: `2000`,
     preAllocatedVUs: `5`,
     maxVUs: `200`,
     timeUnit: '1s',
   },
 },
};

 

更多的S參數配置,請參考

Options reference (k6.io)

 

注入變數給 k6

下面的例子是用 --env 設定變數 MY_USER_AGENT

k6 run script.js --env MY_USER_AGENT="小章"

設定變數可以使用 --env or -e

 

在 test file 讀取變數

然後就可以在測試腳本裡面使用這個變數

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

export default function () {
    console.log(`User agent is '${__ENV.MY_USER_AGENT}'`);
    http.get('http://test.k6.io');
    sleep(1);
}

 

執行結果如下:

 

--env 是給 k6 執行腳本的變數,乍看之下很容易跟系統環境變數搞混

 

注入系統環境變數給 k6

PowerShell

環境變數 $env:name ="vvalue",下面的例子則表示當前的 Process 要注入$env:K6_VUS、$env:K6_DURATION 環境變數

$env:K6_VUS=10 ; $env:K6_DURATION="30s" ; k6 run script.js

 

在 test file 讀取環境變數

讀取環境變數的用法跟讀取變數都是用 __ENV. 前綴開頭加變數名稱,我在 Windows 的環境變數裡面設定了 ASPNETCORE_ENVIRONMENT,在 k6 裡面也可以讀取的到

 

更多的 k6 環境變數,請參考

Supply environment variables

 

測試腳本生命週期

  1. 初始化腳本,載入檔案、匯入 Moudle、定義方法
  2. 設定參數,設定環境變數以及產生測試資料(選項)
  3. VU 只會在 default 方法不斷的反覆執行
  4. 還原測試環境(選項)
// 1. init code
export function setup() {
 // 2. setup code
}
export default function (data) {
 // 3. VU code
}
export function teardown(data) {
 // 4. teardown code
}

 

參考

Test life cycle (k6.io)

 

Metrics

指標衡量系統在測試條件下的表現。默認情況下,k6 會自動收集內置指標。除了內置插件,還可以製作自定義指標。執行 k6 run 之後,就會出現以下 metric,官網已經有很詳細的說明,這裡我就挑我認為重要的列出來

  • http_req_duration:平均每個 http request 所花費的時間。
  • iterations:完成了幾次 http reqest,以及每秒完成幾次。

 

參考

Metrics (k6.io)

 

測試報告

k6 支援許多測試報告視覺化,Results visualization (k6.io) 你可以挑一個你喜歡的,這裡有一個套件可以直接把測試結果轉成 html

benc-uk/k6-reporter: Output K6 test run results as formatted & easy to read HTML reports (github.com)

先 import {htmlReport},然後再調用 htmlReport

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";

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

export default function () {
    console.log(`User agent is '${__ENV.MY_USER_AGENT}'`);
    http.get('http://test.k6.io');
    sleep(1);
}

export function handleSummary(data) {
    return {
        "result.html": htmlReport(data),
        stdout: textSummary(data, { indent: " ", enableColors: true }),
    };
}

 

輸出 stdout、html

k6 run to-html-report.js > result.txt

 

 

 

結論

k6 的文件寫的非常的詳細,這裡僅僅是基本的使用,拋磚引玉,更多的內容都在 k6 doc

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo