K6
在現代網頁與 API 系統開發中,效能測 試是確保系統穩定性的關鍵環節。透過系統性的測試,我們能提前發現潛在瓶頸,確保系統在高併發情況下仍能穩定運作。
什麼是壓力測試?
壓力測試(Stress Testing)是一種軟體測試方法,主要目的是評估系統在極端條件下的穩定性與可靠度。這些極端條件包括:
- 高流量訪問
- 高併發請求
- 大量資料處理
透過壓力測試,我們可以:
- 找出系統的最大承載能力
- 識別潛在瓶頸點
- 觀察系統在超出設計負載時的行為表現
- 確保系統能優雅地處理錯誤情況
常見應用情境
- 電商網站:促銷活動期間的高流量衝擊
- 金融系統:結算時段的高併發交易處理
- API 服務:短時間內大量請求的處理能力
測試類型分類
根據測試目的和強度,可細分為以下幾種類型:
- Smoke Testing(煙霧測試):驗證系統在低配備、正常負載下的基本運作
- Load Testing(負載測試):測量系統在一般及尖峰負載下的效能指標
- Stress Testing(壓力測試):測試系統在高負載或極端條件下的穩定性
- Spike Testing(尖峰測試):模擬瞬間流量驟升的系統反應
- Soak Testing(浸泡測試):測試系統長期運作下的穩定性
安裝與環境設置
使用 Docker 執行 K6
推薦使用 Docker 執行 K6,優點包括:
- 避免複雜的依賴安裝
- 確保跨平台的一致執行環境
- 簡化部署流程
前置需求:
- 已安裝 Docker
- 準備測試腳本(JavaScript)
基礎測試腳本範例
// test.js
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
vus: 10, // 10 個虛擬使用者
duration: "30s", // 測試持續 30 秒
};
export default function () {
const res = http.get("https://test-api.k6.io");
check(res, {
"status is 200": (r) => r.status === 200,
});
sleep(1); // 每次請求間隔 1 秒
}
執行測試
將上述腳本儲存為 test.js
,透過以下指令執行:
docker run --rm -i -v ${PWD}:/scripts -w /scripts grafana/k6 run test.js
指令說明:
--rm
:測試結束後自動移除容器-i
:允許 Docker 接受 stdin 輸入-v ${PWD}:/scripts
:將當前目錄掛載到容器內的/scripts
路徑-w /scripts
: 指定資料夾為 scriptsgrafana/k6
:使用官方 K6 Docker 映像檔run /scripts/test.js
:執行掛載的測試腳本
測試腳本撰寫技巧與實例
K6 使用 JavaScript 撰寫測試腳本,語法直觀且功能強大。以下提供常見情境的實作範例:
1. 基本 GET 請求測試
export default function () {
http.get("https://example.com");
}
2. API 回應內容驗證
const res = http.get("https://example.com/api/user");
check(res, {
"狀態碼為 200": (r) => r.status === 200,
"回應時間 < 1 秒": (r) => r.timings.duration < 1000,
"回傳內容包含 userId": (r) => r.body.includes("userId"),
});
3. 模擬使用者登入(POST 請求)
const payload = JSON.stringify({
username: "admin",
password: "123456",
});
const params = {
headers: { "Content-Type": "application/json" },
};
const res = http.post("https://example.com/api/login", payload, params);
check(res, {
登入成功: (r) => r.status === 200,
});
4. 使用 setup() 函數共享資料
export function setup() {
// 在測試開始前執行,回傳的資料會傳遞給所有虛擬使用者
return { token: "abc123" };
}
export default function (data) {
const res = http.get("https://example.com/api/data", {
headers: { Authorization: `Bearer ${data.token}` },
});
check(res, {
取得資料成功: (r) => r.status === 200,
});
}
5. 解析 HTML 內容
import http from "k6/http";
import { parseHTML } from "k6/html";
export default function () {
const loginPage = http.get("https://example.com/login");
const doc = parseHTML(loginPage.body);
const csrfToken = doc.find('input[name="_token"]').first().attr("value");
// 使用解析出的 CSRF token 進行後續操作
const payload = JSON.stringify({
username: "admin",
password: "123456",
_token: csrfToken,
});
const params = {
headers: { "Content-Type": "application/json" },
};
const res = http.post("https://example.com/login", payload, params);
check(res, {
登入成功: (r) => r.status === 200,
});
}
測試配置選項(options)
options
物件是定義 K6 測試行為的核心配置,包含虛擬使用者數量、測試時間、階段性壓力設定等。
常用配置屬性
屬性名稱 | 資料型別 | 說明 |
---|---|---|
vus | 整數 | 同時執行的虛擬使用者數量(固定負載模式) |
duration | 字串 | 測試總持續時間(如 "30s" 、"1m" 、"2h" ) |
iterations | 整數 | 總執行次數(設定後會覆蓋 duration 與 vus ) |
stages | 陣列 | 多階段壓力測試配置 |
thresholds | 物件 | SLA 門檻條件設定(反應時間、錯誤率等) |
階段性壓力測試範例
export const options = {
stages: [
{ duration: "30s", target: 10 }, // 30秒內緩慢增加至 10 個虛擬使用者
{ duration: "1m", target: 10 }, // 維持 10 個使用者 1 分鐘
{ duration: "30s", target: 0 }, // 30秒內減少至 0
],
};
設定 SLA 門檻範例
export const options = {
thresholds: {
http_req_duration: ["p(95)<500"], // 95% 的請求須在 500ms 內完成
http_req_failed: ["rate<0.01"], // 錯誤率須低於 1%
},
};
測試報告解讀
K6 測試完成後會產生詳細的效能指標報告,以下是主要指標的說明:
核心指標說明
指標名稱 | 說明 |
---|---|
vus | 虛擬使用者數量(Virtual Users) |
iterations | 總執行次數 |
http_req_duration | HTTP 請求耗時統計(平均值、最大值、百分位數) |
http_req_failed | HTTP 請求失敗比例 |
checks | 驗證條件通過率 |
iteration_duration | 單次完整 iteration 的執行時間 |
vus_max | 測試期間的最大虛擬使用者數 |
範例報告解讀
checks.....................: 100.00% ✓ 300 ✗ 0
http_req_duration..........: avg=180ms min=100ms max=350ms p(90)=300ms p(95)=320ms
http_req_failed............: 0.00% ✓ 0 ✗ 300
iterations.................: 2609 22.56/s
vus.......................: 2 min=1 max=100
vus_max...................: 100 min=100 max=100
重點觀察項目:
- 成功率:
checks
和http_req_failed
顯示請求成功率 - 效能表現:
http_req_duration
的各項統計值 - SLA 達成:是否符合預設的效能需求
更多指標詳情可參考:K6 官方指標文檔
如何從 K6 報告推估系統承載能力
雖然 K6 報告不會直接顯示「可承載 X 人同時在線」,但我們可以透過以下方法進行推估:
1. 分析虛擬使用者數量(vus)
vus
代表同時在線的模擬使用者數。若設定 vus: 100
且測試順利通過,表示系統至少可承受 100 人同時在線。
2. 評估回應時間表現
觀察 http_req_duration
的統計數據:
- avg:平均回應時間
- p(95):95% 請求的回應時間
- max:最大回應時間
效能判斷標準:
- p(95) < 500ms:效能良好
- p(95) < 1000ms:效能尚可
- p(95) > 2000ms:可能存在效能瓶頸
3. 檢查錯誤率
http_req_failed
為 0% 表示所有請求都成功處理,系統運作穩定。
4. 計算 QPS(每秒查詢數)
QPS = iterations ÷ duration(秒)
根據 QPS 推算承載人數:
假設每位使用者每 2 秒發送 1 次請求
可承載人數 = QPS × 2
實際計算範例
假設測試結果如下:
vus: 100
duration: 60s
iterations: 10000
http_req_failed: 0.00%
http_req_duration (p95): 350ms
計算過程:
- QPS = 10000 ÷ 60 ≈ 167
- 可承載人數 ≈ 167 × 2 = 約 334 人
結論:系統可以在 1 分鐘內穩定承載約 334 人同時操作,每人每 2 秒發送 1 次請求,且回應時間良好。
最佳實踐建議
測試策略規劃
- 由小到大:從小規模測試開始,逐步增加負載
- 多場景測試:涵蓋不同的使用者行為模式
- 定期執行:將效能測試整合至 CI/CD 流程
腳本撰寫技巧
- 適當的等待時間:使用
sleep()
模擬真實使用者行為 - 詳細的驗證條件:透過
check()
確保回應正確性 - 資料驅動測試:使用外部檔案提供測試資料
結果分析重點
- 關注趨勢變化:比較不同版本的效能表現
- 識別瓶頸點:分析回應時間分布找出問題
- 設定合理 SLA:根據業務需求制定效能標準
結語
K6 是一套現代化、開發者友善的效能測試工具。它具備以下優勢:
- 簡單易用:搭配 Docker 可快速上手
- 功能強大:支援複雜的測試邏輯與驗證
- 程式化測試:使用熟悉的 JavaScript 語法
- 豐富報告:提供詳細的效能指標分析
- CI/CD 整合:容易整合至開發流程
無論是進行 API 單點測試,還是模擬複雜的高併發場景,K6 都能提供準確的數據指標,協助開發團隊做出更好的系統優化決策。
透過系統性的效能測試,我們不僅能確保產品品質,更能在系統上線前就發現並解決潛在問題,為使用者提供更穩定、更快速的服務體驗。