The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

快速上手 Grafana k6 壓力測試工具

如果要問我哪一套壓力測試工具最好用,我會說 k6 絕對是開發者體驗最好的一種,他可以讓你用簡單易懂的 JavaScript 就可以撰寫出各種壓力測試的情境,而且我們這幾年的專案也用了幾次,感覺相當不錯。這篇文章我就帶大家快速上手這套 k6 怎麼用。

安裝 k6 執行檔

k6 有個執行檔需要下載或安裝,透過 Docker 執行也可以,你可以從官網的 Installation 頁面找到完整的安裝說明。

以下我示範 Chocolatey 的安裝方法:

choco install k6 -y

k6

體驗 k6 的開發過程

由於 k6 只是一個壓力測試的執行器,所有的壓測邏輯都要靠 JS 腳本來撰寫,不過程式碼還蠻直覺的,不會很難上手,以下是體驗的步驟。

  1. 撰寫測試情境 ( test.js )

    k6 的測試腳本就是一份很純的 JavaScript / ES6 modules 程式碼:

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

    這裡的 test.k6.io 就是 k6 特別提供給大家做壓力測試的網站。

    這裡最重要的程式碼片段,就是以下這段 k6 的初始化腳本,當壓力測試開始時,每位虛擬使用者(VU)都會去執行這個 export default function () {} 函式,而且每位 VU 在每次 iteration 只會執行一次。

    export default function () {
        // ...
    }
    
  2. 執行測試情境 (預設使用 1 個虛擬使用者進行測試)

    k6 run test.js
    

    執行後你會得到以下測試結果:

    k6 run test.js

    測試結果的資訊含量頗大,需要好好消化一下!

    • scenario: 測試情境

    • VUs: 虛擬使用者人數 (Virtual Users)

    • iterations: 迭代數,也就是重複測試的次數

    • data_received: 從「受測目標」接收到的傳輸量

    • data_sent: 發送到「受測目標」的傳輸量

    • http_req_blocked: 在發出要求前 TCP 連線的等待時間 (等候有空的 TCP 連線)

    • http_req_connecting: 建立到「測試目標」的 TCP 連線時間

    • http_req_duration: 整個 HTTP 的往返時間 (不含 DNS 查詢時間)

      ( http_req_duration = http_req_sending + http_req_waiting + http_req_receiving )

    • http_req_failed: 失敗率

    • http_req_receiving: 從「受測目標」接收到數據的時間

    • http_req_sending: 發送數據到「受測目標」的傳輸時間

    • http_req_tls_handshaking: 進行 TLS 交握的時間

    • http_req_waiting: 等待伺服器回應的時間,也就是俗稱的 time to first byte (TTFB) 時間

    • http_reqs: 總共發出了多少 HTTP 要求

    • iteration_duration: 一次完整 iteration 的時間

    • iterations: 完成幾次 iteration

    • vus: 虛擬使用者人數

    • vus_max: 同時最大與最小虛擬使用者人數

    完整的計量指標可參考 Built-in metrics 文件。

  3. 在既有的測試情境下進行壓力測試

    以下命令可以利用 10 VUs 進行為期 30 秒的壓力測試:

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

    這個命令利用 10 位虛擬使用者,不間斷的持續執行 test.js 中的測試情境,就無窮迴圈一直跑、一直跑,跑到 duration 時間結束為止。

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

    注意: 由於我們的測試腳本有寫到 sleep(1); 這個邏輯,這意味著每位 VU 在執行完 http.get('https://test.k6.io'); 的時候,會停頓 1 秒鐘的時間。

    以下命令可以利用 10 VUs 進行總共 100 次 iterations 的壓力測試:

    k6 run --vus=10 --iterations=100 test.js
    
  4. 你可以將壓力測試的參數寫在程式碼中

    你只要在程式碼中加入以下程式碼片段即可:

    export const options = {
        vus: 10,
        duration: '30s',
    };
    

    現在完整的程式碼如下:

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

    執行測試也只要這樣下指令:

    k6 run test.js
    

    是不是非常直覺!是不是對開發人員特別友善!👍

    備註: 完整的 options 設定可以參考官網的 Options reference 文件。

  5. 嘗試更細緻的壓測情境

    壓力測試有所謂 Ramp up 與 Ramp down 的測試方法,也就是透過不斷遞增或遞減的壓力,對「受測對象」進行不同程度的壓測。

    如下 options 的壓力情境設定,可以這樣解釋:

    • 花 30 秒的時間,從 1 VU 慢慢成長到 20 VUs
    • 然後再花 1 分 30 秒的時間,漸漸的從 20 VUs 降低到 10 VUs
    • 最後花 20 秒的時間,從 10 VUs 降低到 0 VUs,也就是結束壓測!
    export const options = {
        stages: [
            { duration: '30s', target: 20 },
            { duration: '1m30s', target: 10 },
            { duration: '20s', target: 0 },
        ],
    };
    

    壓力測試的過程,可以透過 check 函式檢查 HTTP 回應是否為成功,你可以自行定義檢查的條件。

    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);
    }
    

    測試結果就會額外出現新的 checks 欄位,顯示壓測過程的實際回應狀況!

    status was 200 - checks

相關連結

留言評論