Tools

k6: load test bằng JavaScript, đặt ngưỡng SLO và chạy trong CI

Tóm tắt

k6 viết kịch bản load test bằng JavaScript, tăng giảm tải bằng stages, biến SLO thành thresholds để k6 trả mã lỗi khi không đạt. Nhìn p95 thay vì trung bình, và chỉ test hệ thống của bạn.

"Hệ thống chịu được bao nhiêu người dùng cùng lúc?" là câu hỏi thường chỉ được trả lời sau khi production sập trong đợt khuyến mãi. Load test bị bỏ qua vì công cụ cũ nặng nề, cấu hình bằng giao diện hay XML khó đưa vào Git. k6 của Grafana Labs là công cụ load test hiện đại: viết kịch bản bằng JavaScript, chạy bằng một binary viết bằng Go, đặt ngưỡng chất lượng (threshold) ngay trong code, và trả mã lỗi khi không đạt nên đưa thẳng vào CI được.

Trang GitHub của grafana/k6
Trang GitHub của grafana/k6 (ảnh chụp tháng 11/2026)

GitHub: https://github.com/grafana/k6 · khoảng 32 nghìn sao · Go · AGPL-3.0

Cài đặt

brew install k6                      # macOS
winget install k6 --source winget    # Windows
# Docker: đọc script từ stdin
docker run --rm -i grafana/k6 run - <script.js

Các bản Linux có gói apt/rpm, xem trang cài đặt trong tài liệu Grafana k6.

Kịch bản đầu tiên

// script.js
import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  stages: [
    { duration: "30s", target: 20 },  // tăng dần lên 20 người dùng ảo
    { duration: "1m",  target: 20 },  // giữ 20 người dùng trong 1 phút
    { duration: "15s", target: 0 },   // giảm về 0
  ],
  thresholds: {
    http_req_duration: ["p(95)<500"],  // 95% request phải dưới 500ms
    http_req_failed: ["rate<0.01"],    // tỷ lệ lỗi dưới 1%
  },
};

export default function () {
  const res = http.get("https://staging.example.com/api/products");
  check(res, {
    "status 200": (r) => r.status === 200,
    "có dữ liệu": (r) => r.json("items").length > 0,
  });
  sleep(1); // mô phỏng thời gian người dùng đọc trang
}
k6 run script.js
k6 run --vus 50 --duration 2m script.js     # ghi đè nhanh từ dòng lệnh
k6 run -e BASE_URL=https://staging.example.com script.js

Biến truyền bằng -e được đọc trong script qua __ENV.BASE_URL.

Đọc kết quả

Chỉ sốÝ nghĩa
http_req_durationThời gian phản hồi: avg, p(90), p(95), max. Nhìn p95 thay vì trung bình
http_req_failedTỷ lệ request lỗi
http_reqsTổng số request và số request mỗi giây
checksTỷ lệ check đạt
vusSố người dùng ảo đang chạy

Threshold không đạt thì k6 đánh dấu thất bại và trả mã thoát khác 0, nên CI tự đỏ khi hiệu năng giảm.

Các kiểu test nên có

  • Smoke test: 1–2 người dùng ảo, vài chục giây; kiểm tra kịch bản chạy đúng.
  • Load test: tải bình thường dự kiến trong thời gian dài hơn.
  • Stress test: tăng dần vượt mức bình thường để tìm điểm gãy.
  • Spike test: tăng đột ngột, mô phỏng đợt khuyến mãi hay tin nóng.

Lưu ý

  • Không load test hệ thống không phải của bạn, và báo trước cho team vận hành khi test môi trường dùng chung; tải lớn có thể bị coi như tấn công.
  • Script k6 là JavaScript nhưng không chạy trên Node.js; không dùng trực tiếp được thư viện npm phụ thuộc Node.
  • Máy chạy k6 cũng có giới hạn CPU và mạng; tải rất lớn cần chạy phân tán hoặc dùng dịch vụ cloud.
  • Giấy phép AGPL-3.0: dùng nội bộ để test không vấn đề, nhưng cần xem kỹ nếu sửa đổi và cung cấp k6 như dịch vụ.

Áp dụng thế nào?

  • Dev: Viết smoke test k6 cho các endpoint quan trọng, đặt cạnh code trong thư mục load-tests/.
  • Tech Lead: Biến SLO thành threshold (p95, tỷ lệ lỗi) và chạy load test định kỳ trên staging; so sánh kết quả qua các bản phát hành để phát hiện suy giảm hiệu năng sớm.
  • PM: Trước sự kiện lớn, yêu cầu kết quả stress test với con số cụ thể: chịu được bao nhiêu người dùng đồng thời với p95 dưới ngưỡng nào.

Nguồn & tham khảo

  1. grafana/k6 — grafana (GitHub)
  2. Grafana k6 documentation — grafana