Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là tester cho một sàn thương mại điện tử. Suốt ba tháng, tất cả test case chức năng đều "pass" xanh mướt: thêm vào giỏ hàng chạy tốt, thanh toán chạy tốt, đăng nhập chạy tốt. Sếp yên tâm cho lên production. Rồi đến 0h ngày sale lớn 12/12, hàng trăm nghìn người cùng bấm "Mua ngay" trong một phút. Server sập. Trang trắng xóa. Doanh thu bay hơi hàng tỷ đồng chỉ trong 15 phút. Và câu hỏi đầu tiên của sếp là: "Sao test không phát hiện ra?"
Câu trả lời cay đắng: vì bạn chỉ kiểm thử xem hệ thống làm đúng hay không, mà chưa bao giờ kiểm thử xem hệ thống chịu tải đến đâu. Đó chính là khoảng trống mà Performance Testing (kiểm thử hiệu năng) lấp vào.
Chức năng đúng nhưng chậm rề rề, hoặc chết khi đông người, thì với người dùng cũng như là hỏng. Amazon từng công bố mỗi 100ms chậm đi làm giảm 1% doanh số. Với các nền tảng Việt Nam như Shopee, Tiki, hay app ngân hàng dịp Tết, chậm một giây có thể đồng nghĩa với hàng nghìn khách rời đi. Bài này sẽ giúp bạn phân biệt rõ Load, Stress, Spike, Soak — bốn loại kiểm thử hiệu năng cốt lõi mà bất kỳ QA nào cũng cần nắm, cùng cách lập kế hoạch và đọc kết quả để bảo vệ hệ thống trước những "cú đấm" từ thực tế.
Khái niệm cốt lõi
Performance Testing là hoạt động đo khả năng đáp ứng của hệ thống dưới nhiều mức tải khác nhau: hệ thống phản hồi nhanh cỡ nào, chịu được bao nhiêu người dùng đồng thời, và điều gì xảy ra khi vượt ngưỡng. Nó không quan tâm "nút bấm có ra kết quả đúng không" (đó là kiểm thử chức năng), mà quan tâm "ra kết quả trong bao lâu, và còn ra được khi có 10.000 người cùng bấm không".
Các chỉ số (metrics) bạn phải thuộc
Trước khi phân biệt các loại test, cần nắm bốn nhóm chỉ số nền tảng:
- Response time (thời gian phản hồi): thời gian từ lúc gửi request đến khi nhận đủ response. Thường đo bằng p90/p95/p99 (percentile) thay vì trung bình — vì trung bình che giấu những người dùng xui xẻo nhất. p95 = 2s nghĩa là 95% request nhanh hơn 2 giây.
- Throughput: số request hệ thống xử lý được mỗi giây (RPS — requests per second) hoặc giao dịch mỗi giây (TPS).
- Concurrency / số user ảo (VUs — virtual users): số người dùng "giả lập" cùng thao tác một lúc.
- Tài nguyên hệ thống: CPU, RAM, disk I/O, network, số kết nối database. Đây là nơi bạn tìm ra nút thắt cổ chai (bottleneck).
Bốn loại kiểm thử hiệu năng
| Loại | Mục đích | Cách tăng tải | Câu hỏi cần trả lời |
|---|---|---|---|
| Load | Kiểm tra hệ thống chịu được tải dự kiến ở mức bình thường và cao điểm | Tăng dần đến mức tải mục tiêu rồi giữ ổn định | "Với 5.000 user đồng thời như dự báo, hệ thống có đạt SLA không?" |
| Stress | Tìm giới hạn chịu đựng và điểm gãy của hệ thống | Tăng liên tục vượt mức bình thường cho đến khi hệ thống lỗi | "Hệ thống sập ở đâu? Và khi sập nó sập kiểu gì?" |
| Spike | Kiểm tra phản ứng với tải tăng vọt đột ngột rồi giảm nhanh | Tăng cực nhanh (ví dụ x10 trong vài giây) rồi rút về | "Khi mở bán vé/flash sale, hệ thống có sống sót cú sốc không?" |
| Soak (Endurance) | Kiểm tra độ bền theo thời gian dài | Giữ tải trung bình liên tục nhiều giờ đến vài ngày | "Chạy 12 tiếng liên tục có bị rò rỉ bộ nhớ (memory leak) không?" |
- Load test giống chạy bộ 5km theo kế hoạch — kiểm tra bạn hoàn thành đúng cự ly dự kiến có mệt quá không.
- Stress test giống chạy đến khi kiệt sức để biết giới hạn thể lực thật của bạn ở đâu.
- Spike test giống bị dọa giật mình — tim đập vọt lên rồi có ổn định lại được không.
- Soak test giống chạy marathon 42km — không nhanh, nhưng bền; lộ ra những vấn đề chỉ xuất hiện sau thời gian dài như chuột rút, mất nước.
Vì sao Stress khác Spike?
Đây là chỗ nhiều bạn mới hay nhầm. Cả hai đều đẩy tải cao, nhưng khác về hình dạng của đường tải theo thời gian. Stress tăng từ từ và liên tục để tìm điểm gãy — bạn muốn biết ngưỡng chịu đựng tối đa. Spike tăng đột ngột trong tích tắc rồi rút — bạn muốn biết hệ thống phản ứng ra sao với cú sốc bất ngờ, và quan trọng là nó có phục hồi (recover) được sau đó không. Một hệ thống có thể chịu stress tốt (auto-scale kịp khi tải tăng dần) nhưng lại chết vì spike (scale không kịp cú vọt trong 3 giây).
Tình huống thực tế
Ví dụ 1 — Sàn TMĐT "ShopViet" và đêm sale 12/12 (Spike Test)
ShopViet (giả định) là sàn TMĐT vừa và nhỏ, ngày thường có khoảng 2.000 user đồng thời. Marketing tung chiến dịch flash sale 0h ngày 12/12: giảm 50% cho 1.000 đơn đầu tiên. Đội QA làm load test với 8.000 user và thấy ổn, nên tự tin cho chạy.
Nhưng thực tế đêm đó khác hoàn toàn: đúng 0h00, lượng user vọt từ 2.000 lên 35.000 trong vòng 4 giây — vì mọi người canh sẵn đồng hồ để bấm mua. Đây là spike, không phải load. Kết quả: connection pool tới database cạn kiệt, request xếp hàng, p99 response time nhảy từ 800ms lên 45 giây, rồi server trả lỗi 503 hàng loạt. Flash sale "cháy" theo nghĩa đen — vì trang chết chứ không phải vì hết hàng.
Bài học: Load test không thay thế được spike test. ShopViet đã kiểm tra được "chịu tải cao" nhưng chưa kiểm tra "chịu cú sốc tải cao đột ngột". Sau sự cố, đội QA thêm kịch bản spike x15 trong 5 giây vào bộ test, phát hiện connection pool là bottleneck, tăng pool và bật auto-scaling warm-up trước giờ sale 15 phút. Đợt sale sau chịu được 40.000 user vọt lên mượt mà.
Ví dụ 2 — App ngân hàng và ngày trả lương (Load Test)
Một ngân hàng số tại TP.HCM biết rõ ngày 25 hàng tháng — ngày trả lương phổ biến — lượng giao dịch chuyển khoản tăng gấp 4 lần ngày thường, đạt đỉnh khoảng 12.000 giao dịch/phút vào lúc 8–9h sáng. Đây là tải có thể dự đoán được, nên đội QA làm đúng bài load test.
Họ dựng kịch bản: tăng dần user ảo trong 10 phút đến mức 12.000 giao dịch/phút, giữ nguyên trong 1 giờ, với SLA yêu cầu p95 dưới 3 giây và tỷ lệ lỗi dưới 0,1%. Kết quả lần đầu: p95 lên tới 6,5 giây khi giữ tải — không đạt. Đào sâu vào metrics tài nguyên, họ thấy CPU của service xác thực (authentication) chạm 95% liên tục. Nút thắt nằm ở việc mã hóa mật khẩu (hashing) tốn CPU cho mỗi request. Đội dev thêm caching token và tối ưu, chạy lại đạt p95 = 1,8 giây.
Bài học: Với tải dự đoán được, load test là công cụ chuẩn để xác nhận hệ thống đạt SLA (Service Level Agreement — cam kết mức dịch vụ) trước khi đến ngày cao điểm thật. Và metrics tài nguyên (CPU, RAM) quan trọng ngang response time — chúng chỉ thẳng ra bottleneck nằm ở đâu.
Ví dụ 3 — Nền tảng học trực tuyến và lỗi âm thầm sau 3 ngày (Soak Test)
Một startup edtech ở Đông Nam Á ra mắt tính năng livestream lớp học. Mọi test đều pass, load test 10.000 học viên xem cùng lúc cũng ngon. Nhưng sau khoảng 50–60 giờ chạy production liên tục, hệ thống bắt đầu chậm dần rồi phải restart mỗi 2 ngày một lần vào lúc rạng sáng — gây gián đoạn các lớp học sớm.
Nguyên nhân chỉ lộ ra khi họ chạy soak test: giữ tải trung bình 3.000 user liên tục 72 giờ. Biểu đồ RAM cho thấy bộ nhớ tăng đều đặn không bao giờ giảm — kinh điển của memory leak (rò rỉ bộ nhớ). Mỗi phiên livestream kết thúc nhưng object kết nối WebSocket không được giải phóng, tích tụ dần đến khi hết RAM.
Bài học: Load, stress, spike đều chạy ngắn (vài phút đến vài chục phút) nên không bao giờ phát hiện được rò rỉ bộ nhớ hay đầy log/đầy disk theo thời gian. Chỉ soak test — chạy dài — mới lôi những "sát thủ thầm lặng" này ra ánh sáng.
Hướng dẫn từng bước
Đây là quy trình thực hiện một chiến dịch performance testing bài bản:
- Xác định mục tiêu và SLA/NFR. Trước tiên phải có con số cụ thể: "p95 < 2s, throughput ≥ 500 RPS, error rate < 0,5% với 5.000 user đồng thời". Không có tiêu chí thì test xong không biết pass hay fail. Lấy con số này từ NFR (Non-Functional Requirements — yêu cầu phi chức năng) hoặc từ dữ liệu traffic thực tế (Google Analytics, log server dịp cao điểm năm ngoái).
- Xây dựng mô hình tải (workload model). Phân tích user thật làm gì: 70% duyệt sản phẩm, 20% tìm kiếm, 8% thêm giỏ hàng, 2% thanh toán chẳng hạn. Test phải phản ánh đúng tỷ lệ này, không được "tất cả cùng thanh toán" vì phi thực tế.
- Chọn công cụ. Phổ biến: JMeter (mạnh, giao diện, miễn phí), k6 (viết kịch bản bằng JavaScript, hợp dev/CI), Gatling, Locust (Python). Cloud thì có BlazeMeter, k6 Cloud để tạo tải cực lớn từ nhiều vùng.
- Chuẩn bị môi trường test. Lý tưởng là môi trường giống production (cùng cấu hình server, database có volume dữ liệu tương đương). Test trên máy dev cấu hình yếu rồi suy ra production là sai lầm chết người.
- Chuẩn bị dữ liệu test. Cần đủ tài khoản, sản phẩm, đơn hàng thật để không bị "cache che mắt" (mọi user query cùng 1 sản phẩm sẽ cho kết quả đẹp giả tạo vì được cache).
- Chạy baseline trước. Đo hiệu năng với 1 user để biết mốc "tốt nhất có thể", sau đó mới tăng tải để so sánh mức suy giảm.
- Thực thi từng loại test theo hình dạng tải riêng: load (tăng dần → giữ), stress (tăng đến gãy), spike (vọt đột ngột → rút), soak (giữ dài). Luôn có giai đoạn ramp-up (tăng dần) và ramp-down, đừng bật/tắt đột ngột trừ khi đang cố tình test spike.
- Giám sát song song hai phía. Đo cả phía client (response time, throughput, error) lẫn phía server (CPU, RAM, DB connections, disk). Dùng APM như New Relic, Grafana, Prometheus để nhìn thấy bottleneck.
- Phân tích và báo cáo. So kết quả với SLA. Chỉ ra bottleneck, đề xuất tối ưu (thêm cache, tăng pool, tối ưu query), rồi test lại sau khi fix để xác nhận.
Lỗi thường gặp & mẹo
- Nhầm load với stress/spike. Nhớ: load = tải dự kiến, stress = vượt giới hạn tìm điểm gãy, spike = cú sốc đột ngột, soak = bền theo thời gian. Bốn loại trả lời bốn câu hỏi khác nhau, không thay thế nhau được.
- Chỉ nhìn giá trị trung bình. Trung bình che giấu đuôi xấu. Luôn báo cáo p90/p95/p99. Một hệ thống "trung bình 500ms" vẫn có thể có 5% user chờ 20 giây.
- Test trên môi trường yếu hơn production. Kết quả vô nghĩa. Nếu buộc phải test môi trường nhỏ hơn, phải ghi rõ hệ số quy đổi và nêu giới hạn của kết luận.
- Quên "làm nóng" (warm-up). JVM, cache, connection pool cần thời gian ổn định. Đo ngay giây đầu tiên sẽ ra số xấu giả tạo. Bỏ qua dữ liệu giai đoạn ramp-up khi tính toán.
- Dữ liệu test quá ít nên bị cache đánh lừa. Mọi VU query cùng một record → mọi thứ nhanh giả tạo vì cache. Dùng dữ liệu đa dạng, đủ lớn.
- Bỏ qua soak test vì "mất thời gian". Đây là loại duy nhất bắt được memory leak và đầy disk. Bỏ qua nó là bỏ ngỏ nhóm lỗi nguy hiểm nhất — lỗi chỉ xuất hiện sau nhiều giờ chạy.
- Chạy load test bắn thẳng vào production thật khi không được phép — có thể gây sự cố thật cho khách hàng. Luôn xin phép và ưu tiên môi trường staging.
- Mẹo giám sát: khi hệ thống bắt đầu gãy, nhìn xem chỉ số nào chạm trần trước (CPU? RAM? DB connections?) — đó gần như chắc chắn là bottleneck cần xử lý đầu tiên.
Bài tập thực hành
- Phân loại tình huống. Với mỗi tình huống dưới đây, xác định nên dùng loại test nào (Load / Stress / Spike / Soak) và giải thích:
- Viết tiêu chí pass/fail. Cho một API đăng nhập, hãy viết bộ SLA đầy đủ gồm: response time (dạng percentile), throughput mục tiêu, error rate tối đa, và mức user đồng thời. Con số do bạn đề xuất, miễn hợp lý.
- Đọc kết quả. Một load test cho ra: p50 = 400ms, p95 = 1,8s, p99 = 9s, error rate = 0,3%, CPU database = 98%. SLA yêu cầu p95 < 2s, p99 < 3s, error < 0,5%. Hệ thống pass hay fail? Bottleneck nghi ngờ nằm ở đâu? Bạn đề xuất bước tiếp theo là gì?
- Thực hành (nâng cao). Cài k6, viết một kịch bản đơn giản gửi request tới một API công khai (ví dụ một endpoint test của chính bạn), cấu hình ramp-up 0→50 VU trong 30 giây, giữ 1 phút, rồi ramp-down. Đọc report và ghi lại p95, throughput.
Tóm tắt
- Performance Testing đo khả năng đáp ứng của hệ thống dưới các mức tải, tập trung vào nhanh và bền chứ không phải đúng hay sai.
- Bốn loại cốt lõi: Load (tải dự kiến, kiểm tra SLA), Stress (vượt giới hạn tìm điểm gãy), Spike (cú sốc đột ngột và khả năng phục hồi), Soak (độ bền dài hạn, bắt memory leak). Chúng khác nhau ở hình dạng đường tải theo thời gian và trả lời những câu hỏi khác nhau.
- Luôn đo bằng percentile (p95/p99) thay vì trung bình, và giám sát song song cả response time lẫn tài nguyên server để tìm bottleneck.
- Quy trình chuẩn: xác định SLA → mô hình tải thực tế → môi trường giống production → chạy baseline → thực thi từng loại → giám sát hai phía → phân tích và test lại sau khi fix.
- Ba bài học từ thực tế: load test không cứu bạn khỏi spike (ShopViet), metrics tài nguyên chỉ thẳng ra bottleneck (app ngân hàng), và chỉ soak test mới bắt được rò rỉ bộ nhớ (edtech).