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:
- 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.
- 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%.
- 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.
- 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.
- 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.
- 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.
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)
}
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"})
- 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.
- 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.