# Load testing requests với k6 trên Ubuntu 22.04 Dưới đây là tóm tắt các kỹ thuật “load test” (kiểm thử tải) cho request trong lập trình và hệ thống web/API: ## 1) Khái niệm và mục tiêu - Load testing: Đo khả năng hệ thống xử lý tải mong đợi (số request/giây, số người dùng đồng thời) với tỉ lệ lỗi và độ trễ chấp nhận được. - Liên quan: - Stress test: Đẩy quá tải để tìm ngưỡng sập và hành vi khi quá tải. - Spike test: Tải tăng đột biến trong thời gian ngắn. - Soak/Endurance test: Chạy tải vừa phải lâu dài để phát hiện rò rỉ tài nguyên. - Capacity test: Xác định mức tải tối đa trước khi vi phạm SLO. ## 2) Chỉ số quan trọng cần theo dõi - RPS/QPS (request/giây), số user đồng thời (concurrency). - Độ trễ theo phân vị: p50, p90, p95, p99, max; TTFB. - Tỉ lệ lỗi (HTTP 5xx/4xx), timeouts, retries. - Tài nguyên: CPU, RAM, I/O, GC, băng thông, connection pool, thread/worker. - Phụ thuộc ngoài: DB (latency, locks), cache, message queue, dịch vụ downstream. - SLO/SLA: ví dụ p95 < 300 ms, lỗi < 0.1%. ## 3) Mô hình tải - Open model (arrival-rate): Điều khiển tốc độ đến (ví dụ 100 RPS). Phù hợp hệ thống web công khai. - Closed model (vus/users): Điều khiển số người dùng ảo, mỗi user có think-time. Phù hợp mô phỏng phiên người dùng. - Hình dạng tải: ramp-up, steady-state, ramp-down; spike; step; sinus. - Warm-up: chạy nhẹ để làm nóng cache/JIT/opcache trước khi đo. ## 4) Quy trình thực hiện - Xác định mục tiêu: SLO, kịch bản sử dụng, dữ liệu thực tế. - Thiết kế kịch bản: Đường đi người dùng, tỉ lệ endpoint, think-time, phân phối payload, tham số hóa và tương quan (correlation) token/session. - Dữ liệu: Data set đủ lớn, ID duy nhất để tránh cache giả, idempotency khi POST. - Môi trường: Gần giống production (cấu hình, dữ liệu, phiên bản). Tắt/bật cache tùy mục tiêu (cold vs warm). - Thực thi: Ramp-up từ từ, giữ steady >= 10–30 phút (hoặc lâu hơn với soak), dừng theo điều kiện lỗi/latency. - Quan sát: Log + APM + tracing + metrics (Prometheus/Grafana). Gắn nhãn test để phân tích. - Phân tích: Tìm “plateau” throughput, điểm gãy p95/p99, lỗi tăng, tài nguyên bão hòa. Áp dụng Little’s Law (L = λ W) để suy luận hàng đợi. - Lặp lại: Tối ưu (DB index, cache, pool, batching), đo lại. ## 5) Kỹ thuật thực hành tốt - Parameterization và correlation: Trích token CSRF/JWT từ response và dùng cho request tiếp theo. - Think-time và pacing: Mô phỏng hành vi người dùng thật. - Connection reuse: HTTP/1.1 keep-alive, HTTP/2, gRPC; TLS session reuse. - Retries với backoff + jitter; tôn trọng rate limit. - Phân tách đọc/ghi; thử với cache cold vs warm. - Test lỗi từng phần: Circuit breaker, timeouts, bulkhead, chaos (latency injection). - Phân tán generator: Nhiều injector để tránh nghẽn client (CPU, NIC). - Tránh “coordinated omission”: Ưu tiên open model (RPS cố định) khi đo latency. - Dọn state: Reset dữ liệu, cleanup để run lặp lại nhất quán. ## 6) Công cụ phổ biến - Kịch bản phong phú: - k6 (JavaScript), Locust (Python), Gatling (Scala), Artillery (YAML/JS). - Đơn giản/CLI: - wrk, vegeta, hey, ab (ApacheBench). - Trình duyệt/end-to-end: - Playwright/Test + tracing; nhưng không thay thế API load test. - APM/Observability: - OpenTelemetry, Jaeger, Prometheus/Grafana. ## 7) Ví dụ nhanh ### k6 (open model theo RPS) ```javascript import http from 'k6/http'; import { check, sleep } from 'k6'; export const options = { scenarios: { steady_rps: { executor: 'constant-arrival-rate', rate: 200, // 200 RPS timeUnit: '1s', duration: '10m', preAllocatedVUs: 50, maxVUs: 200, }, }, thresholds: { http_req_duration: ['p(95)<300'], http_req_failed: ['rate<0.001'], }, }; export default function () { const res = http.get('https://api.example.com/items?limit=20'); check(res, { 'status is 200': r => r.status === 200 }); sleep(1); // think-time (tác dụng trong closed model) } ``` ### Locust (closed model theo số user): ```python from locust import HttpUser, task, between class WebsiteUser(HttpUser): wait_time = between(1, 3) # think-time @task(3) def list_items(self): self.client.get("/items?limit=20") @task(1) def create_item(self): self.client.post("/items", json={"name": "foo"}) ``` ## 8) Cách đọc kết quả - Throughput “plateau” dù tăng tải => nghẽn tài nguyên (CPU, DB, pool). - p95/p99 tăng mạnh khi tăng tải nhẹ => đụng hàng đợi. - Lỗi 5xx/timeout tăng cùng latency => quá tải hoặc cấu hình timeout/pool nhỏ. - Soak test: memory tăng dần, GC/FD leak => rò rỉ tài nguyên. ## 9) Lỗi thường gặp - Test từ máy yếu/băng thông thấp => nghẽn ở client. - Dữ liệu lặp lại gây cache hit bất thường. - Bỏ qua warm-up hoặc chạy quá ngắn. - Chỉ nhìn trung bình, bỏ p95/p99. - Không tách ảnh hưởng CDN/WAF/Rate limit. Gợi ý cho ứng dụng PHP/Laravel/Phalcon - PHP-FPM, DB, Nginx, cache... - Dùng k6/Locust để mô phỏng mix đọc/ghi, theo dõi p95/p99 và tỉ lệ lỗi.