Mở đầu — vì sao bài này quan trọng
Bạn đã chạy load test. Bạn có một mớ số liệu đẹp: P95 latency, throughput, error rate. Sếp bước qua bàn và hỏi một câu tưởng chừng đơn giản: "Vậy Tết này tụi mình cần bao nhiêu server?"
Nếu bạn ú ớ, hoặc trả lời kiểu "chắc là… thêm vài con nữa cho chắc", thì bạn vừa để lỡ khoảnh khắc quan trọng nhất của cả quá trình performance testing. Bởi vì test không phải để có báo cáo đẹp. Test là để ra quyết định về hạ tầng — và quyết định đó tốn tiền thật, ảnh hưởng trực tiếp đến doanh thu và trải nghiệm người dùng.
Capacity planning (hoạch định năng lực) chính là chiếc cầu nối giữa "con số load test" và "quyết định mua bao nhiêu máy, cấu hình bao nhiêu pod, đặt auto-scaling ở ngưỡng nào". Đây là kỹ năng phân biệt một người "biết chạy tool" với một Performance Engineer thực thụ. Trong bài này, mình sẽ chỉ cho bạn cách biến dữ liệu load test thành một con số hạ tầng cụ thể, có căn cứ, có biên an toàn — con số mà bạn dám bảo vệ trước cả sếp kỹ thuật lẫn sếp tài chính.
Lưu ý: bài này không dạy cách đọc report hay tìm điểm nghẽn (đó là việc của các bài khác). Ở đây ta giả định bạn đã có số liệu sạch trong tay, và tập trung 100% vào bài toán: từ số liệu → quyết định kích thước hạ tầng.
Khái niệm cốt lõi
Capacity planning về bản chất là một phép chia. Nhưng để phép chia đó đúng, bạn cần hiểu rõ ba nhóm đầu vào và một vài công thức nền tảng.
Ba nhóm đầu vào bắt buộc
1. Nhu cầu đỉnh dự kiến (Peak demand). Đây là con số đến từ business, không phải từ kỹ thuật. Bao nhiêu người dùng đồng thời? Bao nhiêu request mỗi giây (RPS) vào giờ cao điểm? Con số này thường lấy từ dữ liệu lịch sử (Google Analytics, log production) nhân với dự báo tăng trưởng. Ví dụ: "Năm ngoái đỉnh 3.000 RPS, năm nay marketing dự báo tăng 40%, cộng thêm campaign 12.12 nên nhân tiếp hệ số 2" → peak dự kiến ≈ 8.400 RPS.
2. Mục tiêu SLA/SLO. Bạn muốn giữ chất lượng ở mức nào? Thường phát biểu dạng: "P95 latency < 500ms và error rate < 0,1% ở mức tải đỉnh". Đây là ranh giới đỏ — vượt qua nó nghĩa là hệ thống "gãy" theo định nghĩa kinh doanh, dù server vẫn còn chạy.
3. Năng lực một đơn vị (Single-instance capacity). Đây là phần bạn đo được từ load test: một instance (một server, một pod, một container với cấu hình cố định) có thể chịu tối đa bao nhiêu RPS mà vẫn nằm trong SLA? Chú ý cụm "mà vẫn nằm trong SLA" — nó là chìa khóa. Một máy có thể xử lý 2.000 RPS nhưng nếu tại 2.000 RPS thì P95 đã vọt lên 3 giây, thì năng lực hữu ích của nó không phải 2.000.
Đường cong hiệu năng và "knee point"
Khi bạn tăng tải dần lên một instance, latency không tăng tuyến tính. Ban đầu nó gần như phẳng, rồi đến một điểm gọi là knee point (điểm gãy khớp), latency bắt đầu dựng đứng. Năng lực hữu ích của instance chính là mức RPS ngay trước knee point, hoặc mức RPS mà tại đó SLA vừa chạm ngưỡng — lấy cái nào đến trước.
graph LR
A[Tải thấp<br/>latency phẳng] --> B[Vùng tuyến tính<br/>latency tăng nhẹ]
B --> C[Knee point<br/>SLA chạm ngưỡng]
C --> D[Vùng bão hòa<br/>latency dựng đứng]Đừng bao giờ lấy năng lực ở vùng bão hòa. Đó là vùng "server chưa chết nhưng người dùng đã bỏ đi".
Công thức nền tảng
Số instance cần thiết được tính như sau:
Số instance = ceil( Peak RPS dự kiến / Năng lực hữu ích mỗi instance ) × Hệ số an toàn
Trong đó hệ số an toàn (headroom) thường là 1.3–1.5 (tức chừa 30–50% dư địa). Vì sao cần dư địa?
- Traffic thực tế giật cục (bursty), không mượt như test.
- Bạn cần chỗ trống để chịu được khi một instance chết (fault tolerance).
- Bạn cần thời gian cho auto-scaling kịp phản ứng (scale không tức thời).
- Rolling deployment sẽ tạm thời rút bớt instance.
Little's Law — người bạn định lượng
Định luật Little cho phép bạn nối ba đại lượng: số request đang xử lý đồng thời (concurrency), throughput và thời gian xử lý.
Concurrency = Throughput × Response time
Ví dụ: nếu bạn muốn đạt 5.000 RPS và mỗi request mất trung bình 200ms (0,2s) để xử lý, thì tại bất kỳ thời điểm nào hệ thống phải "ôm" đồng thời:
5.000 × 0,2 = 1.000 request đang xử lý cùng lúc
Con số 1.000 này quyết định bạn cần bao nhiêu thread pool, bao nhiêu connection tới database, kích thước queue ra sao. Little's Law là lý do vì sao đôi khi giảm được response time lại giúp bạn tiết kiệm server — vì cùng throughput nhưng cần ít concurrency hơn.
Tình huống thực tế
Ví dụ 1 — Sàn TMĐT chuẩn bị cho 12.12
Công ty ShopViet (giả định) đang chạy một sàn thương mại điện tử. Đội performance được giao nhiệm vụ: đảm bảo hệ thống checkout sống sót qua đợt flash sale 12.12.
Đầu vào business: năm ngoái đỉnh checkout là 1.200 RPS. Năm nay dự báo lượng người dùng tăng 60%, và riêng flash sale 12.12 tạo đỉnh gấp 2,5 lần ngày thường. Peak dự kiến:
1.200 × 1,6 × 2,5 = 4.800 RPS
SLA: P95 < 800ms, error < 0,5%.
Đội chạy k6 test trên một pod (2 vCPU, 4GB RAM). Kết quả: pod giữ được SLA đến 340 RPS; vượt 380 RPS thì P95 nhảy lên 1,4 giây (đây là knee point). Vậy năng lực hữu ích = 340 RPS/pod.
Tính toán:
Số pod tối thiểu = 4.800 / 340 = 14,1 → làm tròn lên 15 pod
Áp headroom 1,4 (chừa dư địa flash sale) = 15 × 1,4 = 21 pod
Đội quyết định cấu hình auto-scaling: chạy nền 15 pod, scale tối đa 24 pod, ngưỡng scale-out khi CPU > 65%.
Bài học rút ra: con số peak đến từ business, nhưng đội performance mới là người phiên dịch nó thành số pod. Nếu chỉ lấy 4.800 / 340 = 15 pod mà không cộng headroom, ngày 12.12 khi một pod bị OOM-kill và traffic giật, hệ thống sẽ đổ dây chuyền. 6 pod dư địa chính là khoản "bảo hiểm" rẻ hơn nhiều so với một giờ sập checkout.
Ví dụ 2 — Fintech và bài toán "downstream giới hạn"
PayFast (giả định) là một cổng thanh toán. Họ test API xác thực giao dịch và thấy mỗi instance app chịu được tới 900 RPS trong SLA. Đội tính: cần 3.000 RPS đỉnh → 4 instance là dư.
Nhưng khi triển khai thử với 4 instance, hệ thống sập ở 2.100 RPS. Vì sao? Vì mỗi giao dịch phải gọi sang ngân hàng đối tác, và đường truyền đó chỉ chịu được 2.000 RPS trước khi bên ngân hàng bắt đầu trả lỗi timeout.
Đây là bài học kinh điển: năng lực của hệ thống bằng năng lực của mắt xích yếu nhất, không phải mắt xích bạn tình cờ test. Đội PayFast test app tier nhưng quên test cả chuỗi (service chain). Năng lực hữu ích thực sự của toàn hệ thống là 2.000 RPS chứ không phải 3.600.
Áp dụng Little's Law để hiểu nút thắt: ngân hàng đối tác cho phép tối đa 300 kết nối đồng thời, mỗi giao dịch mất 150ms. Vậy trần throughput = 300 / 0,15 = 2.000 RPS. Đúng bằng con số họ thấy sập.
Bài học rút ra: capacity planning phải làm ở cấp hệ thống, xác định trần của từng tier (app, DB, cache, dịch vụ bên thứ ba) rồi lấy trần thấp nhất. Thêm server ở tier đã dư thừa chỉ đốt tiền vô ích. Giải pháp của PayFast không phải mua thêm app server, mà là đàm phán nâng hạn mức với ngân hàng và thêm hàng đợi (queue) để làm mượt các đỉnh giật.
Ví dụ 3 — Startup SaaS và chi phí đám mây
LearnHub (giả định) là startup edtech chạy trên AWS. Họ có 40.000 người dùng, dự báo cuối năm lên 100.000. CFO hỏi: "Chi phí hạ tầng năm sau là bao nhiêu?"
Đội performance đo được: mỗi instance c5.large (giá ~72 USD/tháng) chịu 250 RPS trong SLA. Từ log production, tỉ lệ RPS/người-dùng-hoạt-động là khoảng 0,05 RPS mỗi user ở giờ đỉnh.
Dự phóng:
Peak RPS tương lai = 100.000 × 0,05 = 5.000 RPS
Số instance = 5.000 / 250 = 20 instance
Áp headroom 1,3 = 26 instance
Chi phí đỉnh = 26 × 72 = 1.872 USD/tháng
Nhưng đội đi thêm một bước tinh tế: traffic edtech dao động mạnh theo giờ (đỉnh buổi tối, thấp ban ngày, cuối tuần khác ngày thường). Trung bình cả ngày chỉ ở khoảng 40% đỉnh. Với auto-scaling, chi phí thực tế ước tính chỉ ~55% chi phí đỉnh:
Chi phí thực tế ≈ 1.872 × 0,55 ≈ 1.030 USD/tháng
Bài học rút ra: capacity planning không chỉ trả lời "cần bao nhiêu máy khi đỉnh" mà còn "trung bình tốn bao nhiêu tiền". Con số dành cho CFO là chi phí trung bình có tính đến auto-scaling, không phải chi phí đỉnh cố định. Biết chuyển đổi giữa hai con số này giúp bạn được coi là người hiểu cả kỹ thuật lẫn kinh doanh.
Hướng dẫn từng bước
Đây là quy trình 7 bước để đi từ dữ liệu load test đến quyết định hạ tầng.
Bước 1 — Chốt số peak từ business. Lấy dữ liệu đỉnh lịch sử (từ log production hoặc analytics, đo bằng RPS chứ không phải "số user" mơ hồ), nhân với hệ số tăng trưởng dự báo và hệ số sự kiện đặc biệt (sale, khai giảng, mùa vụ). Ghi rõ giả định — con số này sẽ bị chất vấn.
Bước 2 — Chốt SLA rõ ràng, đo được. Ví dụ: P95 < 500ms, P99 < 1s, error < 0,1%. Không có SLA thì không có khái niệm "năng lực", vì bạn không biết đâu là ranh giới chấp nhận được.
Bước 3 — Đo năng lực một instance. Chạy load test tăng dần (ramping) trên đúng một instance với cấu hình production. Tìm mức RPS cao nhất mà tại đó SLA vẫn được giữ. Đây là số quan trọng nhất, phải đo chứ không đoán. Chạy vài lần để chắc kết quả ổn định.
Bước 4 — Tìm mắt xích yếu nhất. Test cả chuỗi service, không chỉ app tier. Xác định trần của DB, cache, message queue, dịch vụ bên thứ ba. Năng lực hệ thống = trần thấp nhất. Đừng bỏ qua bước này (nhớ bài học PayFast).
Bước 5 — Tính số instance thô. Peak RPS / Năng lực hữu ích mỗi instance, làm tròn lên.
Bước 6 — Cộng headroom và cấu hình auto-scaling. Nhân hệ số an toàn 1.3–1.5. Đặt số instance nền (baseline), số tối đa (max), và ngưỡng scale-out (thường CPU 60–70% hoặc RPS/instance chạm ~70% năng lực). Cấu hình cả tốc độ scale để kịp với độ dốc traffic của bạn.
Bước 7 — Kiểm chứng và viết ra giả định. Chạy lại một test ở đúng quy mô đã tính để xác nhận. Viết tài liệu ngắn: peak giả định bao nhiêu, đo được gì, kết luận cần bao nhiêu, headroom bao nhiêu, chi phí ước tính. Tài liệu này là thứ bảo vệ bạn khi có sự cố.
Lỗi thường gặp & mẹo
Lỗi 1 — Lấy năng lực ở vùng bão hòa. Nhiều người lấy mức RPS cao nhất mà server "chưa sập" làm năng lực. Sai. Ở đó latency đã tệ, người dùng đã khổ. Luôn lấy năng lực trong SLA, tức trước knee point.
Lỗi 2 — Quên headroom. Tính chính xác vừa đủ nghe rất "tối ưu", nhưng thực tế traffic giật cục, instance chết, deploy rolling — tất cả ăn vào dư địa. Không có headroom là mời gọi sự cố. Tối thiểu chừa 30%.
Lỗi 3 — Ngoại suy tuyến tính. "Một máy 300 RPS thì mười máy là 3.000 RPS" — chỉ đúng nếu không có nút thắt chung. Trong thực tế database, cache, connection pool hay dịch vụ bên thứ ba thường là trần chung. Càng thêm app server, bạn càng nhanh chạm trần đó chứ không nhân được tuyến tính.
Lỗi 4 — Test sai môi trường. Đo năng lực trên máy dev mạnh hơn (hoặc yếu hơn) production rồi suy ra. Năng lực instance phụ thuộc cấu hình cụ thể — CPU, RAM, network, phiên bản runtime. Phải đo trên cấu hình giống production.
Lỗi 5 — Chỉ nghĩ đỉnh, quên trung bình. Với đám mây và auto-scaling, chi phí thực tế là tích phân theo thời gian, không phải con số đỉnh. Báo cáo cả hai.
Mẹo — Dùng RPS/user hoặc RPS/đơn-hàng làm "hệ số quy đổi". Thay vì đoán peak RPS trực tiếp, hãy tính tỉ lệ từ production (ví dụ 0,05 RPS mỗi user hoạt động), rồi nhân với dự báo số user của business. Cách này minh bạch và dễ bảo vệ hơn nhiều.
Mẹo — Lập bảng "what-if". Thay vì một con số, hãy trình bày một bảng: nếu peak 4.000 RPS → 16 pod; 6.000 → 24 pod; 8.000 → 32 pod. Sếp thích thấy các kịch bản và ngưỡng chi phí tương ứng để ra quyết định.
Mẹo — Tách năng lực đọc và ghi. Endpoint đọc (nhẹ) và endpoint ghi/thanh toán (nặng) có năng lực rất khác nhau. Đừng gộp chung một con số "RPS trung bình" — hãy plan riêng cho các luồng quan trọng.
Bài tập thực hành
Bài 1 — Tính cơ bản. Một API có năng lực hữu ích 420 RPS/instance (trong SLA P95 < 600ms). Business dự báo peak 5.500 RPS. Với headroom 1,4, bạn cần bao nhiêu instance? (Đáp án gợi ý: ceil(5500/420)=14, ×1,4 = 19,6 → 20 instance.)
Bài 2 — Little's Law. Bạn muốn đạt throughput 8.000 RPS, response time trung bình 250ms. Cần bao nhiêu request đồng thời? Nếu connection pool tới DB chỉ có 1.500, hệ thống có nghẽn không? (Gợi ý: 8000 × 0,25 = 2.000 concurrency > 1.500 → DB pool là nút thắt, cần nâng pool hoặc giảm response time.)
Bài 3 — Tình huống tổng hợp. Cho một sàn TMĐT: đỉnh năm ngoái 900 RPS, tăng trưởng dự báo 50%, sự kiện sale nhân 2. Mỗi pod chịu 260 RPS trong SLA. DB tier chạm trần ở 3.500 RPS. Hãy: (a) tính peak dự kiến, (b) tính số pod thô, (c) chỉ ra liệu DB có phải nút thắt không, (d) đề xuất cấu hình auto-scaling với headroom 1,35. Viết một đoạn 5–7 câu trình bày kết luận như thể báo cáo cho sếp.
Bài 4 — Tư duy chi phí. Instance của bạn giá 90 USD/tháng, cần 22 instance ở đỉnh. Nếu traffic trung bình chỉ bằng 45% đỉnh và bạn dùng auto-scaling, ước tính chi phí trung bình hàng tháng. So sánh với phương án chạy cố định 22 instance 24/7.
Tóm tắt
Capacity planning là bước biến load test từ "báo cáo đẹp" thành "quyết định hạ tầng có căn cứ". Cốt lõi nằm ở một phép chia: Peak RPS dự kiến chia cho năng lực hữu ích mỗi instance, rồi nhân hệ số an toàn.
Ba điều cần khắc cốt ghi tâm:
- Năng lực phải đo trong SLA, lấy ở mức trước knee point — không phải mức server "chưa sập".
- Hệ thống mạnh bằng mắt xích yếu nhất — luôn tìm trần của DB, cache, dịch vụ bên thứ ba, đừng ngoại suy tuyến tính.
- Luôn cộng headroom (30–50%) và báo cáo cả chi phí đỉnh lẫn chi phí trung bình khi có auto-scaling.
Concurrency = Throughput × Response time) là công cụ định lượng giúp bạn hiểu nút thắt và thấy vì sao giảm latency đôi khi tiết kiệm được cả server. Và cuối cùng: hãy luôn viết ra giả định của mình. Con số hạ tầng bạn đưa ra sẽ bị chất vấn — người có tài liệu rõ ràng về peak, SLA, năng lực đo được và headroom chính là người ra quyết định đáng tin cậy, chứ không phải người đoán "thêm vài con cho chắc".