Nền tảng Cơ bản 6 phút đọc

Từ vựng về scale: Throughput, Latency, QPS, SLA

Sáu từ mà mọi cuộc thảo luận thiết kế hệ thống đều dùng: throughput vs latency, vertical vs horizontal, QPS, p50/p99, SLA vs SLO vs SLI. Định nghĩa cho .NET engineer.

Mục lục
  1. Throughput vs latency nghĩa là gì - và vì sao đánh đổi?
  2. Vì sao báo p50, p95, p99 thay vì trung bình?
  3. Scale dọc và scale ngang khác nhau ra sao?
  4. Cần thuộc số nào để suy nghĩ bằng QPS?
  5. SLI, SLO, SLA quan hệ với nhau ra sao?
  6. Bộ từ vựng này trông ra sao trong service .NET thật?
  7. Khi nào bộ từ vựng này không còn hữu ích?
  8. Đi tiếp đâu từ đây?

Các cuộc thảo luận thiết kế hệ thống diễn ra nhanh vì mọi người dùng chung sáu từ: throughput, latency, scale dọc, scale ngang, QPS, percentile. Nếu các từ ấy mang nghĩa khác nhau với hai người trong phòng, cuộc thảo luận chỉ là vô nghĩa. Chương này định nghĩa chúng một lần, theo cách phần còn lại của series sẽ dùng, và gắn mỗi từ vào một công cụ .NET đo được thật.

Throughput vs latency nghĩa là gì - và vì sao đánh đổi?

Throughput là số request hệ thống xử lý xong mỗi giây (req/s, thường viết tắt QPS - "queries per second"). Latency là thời gian một request chờ trước khi nhận response (ms).

Đây không phải cùng một trục. Một service có thể vừa throughput cao vừa latency cao (job batch trả 10000 kết quả trong 5 giây), hoặc throughput thấp + latency thấp (máy dev một user). Sự đánh đổi xuất hiện dưới tải: khi đẩy QPS gần trần hệ thống, queue hình thành, queue làm tăng latency. Định luật Little nói rõ quan hệ:

số request đồng thời trung bình = throughput * latency trung bình

Phục vụ 1000 req/s với latency trung bình 50 ms thì có 50 request đồng thời đang xử lý. Đẩy lên latency 100 ms là 100 đồng thời - nghĩa là áp lực thread/connection pool nhiều hơn, GC nhiều hơn, contention nhiều hơn, và latency tăng tiếp. Vòng lặp phản hồi này là lý do các service sập phi tuyến khi quá tải kéo dài.

graph LR
    QPS[Throughput tăng] --> Q[Queue lớn]
    Q --> Lat[Latency tăng]
    Lat --> Conc[Đồng thời tăng]
    Conc --> Press[Áp lực tài nguyên]
    Press --> Lat
    style Lat fill:#fbb,stroke:#c00

Vì sao báo p50, p95, p99 thay vì trung bình?

Phân phối latency không phải normal - đuôi dày. Một web service điển hình có thể là 30 ms cho 95/100 request, rồi 200 ms cho 4, rồi 2000 ms cho 1. Trung bình là 56 ms; user chờ 2 giây không thấy "trung bình" gì.

Percentile cắt phân phối trung thực. p50 (median) - một nửa user chờ tối đa số này. p95 - 1 trong 20 chờ lâu hơn. p99 - 1 trong 100. p99.9 - 1 trong 1000, con số đánh thức oncall.

Hai service có cùng trung bình có thể có p99 khác hẳn. Chọn percentile khớp nỗi đau user của bạn - p95 cho UX bình thường, p99 cho luồng giao dịch, p99.9 cho API thanh toán. Instrumentation OpenTelemetry của ASP.NET Core emit trực tiếp:

builder.Services.AddOpenTelemetry()
    .WithMetrics(b => b
        .AddAspNetCoreInstrumentation()    // histogram http.server.request.duration
        .AddRuntimeInstrumentation()        // GC, thread pool
        .AddPrometheusExporter());

Rồi trong Grafana query histogram_quantile(0.99, ...) là có số. Chương 13 xử lý phần dây nối; chương này chỉ đặt kỳ vọng mọi tuyên ngôn về latency phải nói rõ percentile.

Scale dọc và scale ngang khác nhau ra sao?

Scale dọc (vertical) là làm một máy lớn hơn - nhiều CPU, nhiều RAM, đĩa nhanh hơn. Trần là giá single-box tăng siêu tuyến: tier CPU kế tiếp thường giá 4x cho 2x hiệu năng, và đến lúc nào đó bạn trả tiền cho phần cứng không có trên menu của cloud provider.

Scale ngang (horizontal) là thêm nhiều máy chia tải. Trần ở đây là chi phí phối hợp: các máy phải đồng thuận về data, điều hướng traffic giữa nhau, fail over khi một con chết. Tier web stateless scale ngang gần như miễn phí; database stateful thì không.

Bậc thang thực dụng cho service .NET: scale dọc tier web trước (đi từ 4 lên 16 vCPU trên App Service plan); khi một máy không đủ thì thêm replica sau load balancer; khi một database là điểm nghẽn thì thêm read replica; chỉ khi cái đó cũng đầy mới nhìn sang sharding. Mỗi bước rẻ hơn bước tiếp theo; nhảy bước chỉ khi có bằng chứng.

Cần thuộc số nào để suy nghĩ bằng QPS?

Số tròn hữu ích cho ước lượng nhanh:

Chương 2 (back-of-envelope) luyện những con số này nghiêm túc.

SLI, SLO, SLA quan hệ với nhau ra sao?

Ba vòng tròn lồng nhau, dung sai từ nhỏ đến lớn:

Số học: 99.9% trong 30 ngày = 43 phút downtime cho phép. 99% = 7.2 giờ. Phép tính căng nhanh. Hai sự cố hai giờ trong một quý đã thổi bay SLO 99.9%. Kỷ luật viết SLO ra giấy ép cuộc trò chuyện trung thực về tính năng nào xứng đáng thêm số 9 và tính năng nào có thể xuống cấp được.

Bộ từ vựng này trông ra sao trong service .NET thật?

Một service ASP.NET Core đơn giản lộ cả bộ từ điển trong một lệnh qua dotnet-counters:

// Chạy từ command line trên instance đã deploy:
// dotnet-counters monitor --process-id <pid>
//   System.Runtime
//   Microsoft.AspNetCore.Hosting
//   Microsoft.AspNetCore.Server.Kestrel

// Bạn sẽ thấy live, mỗi giây:
//   - requests-per-second                    (throughput / QPS)
//   - current-requests                       (N theo Little's Law)
//   - request-duration histogram             (phân phối latency)
//   - cpu-usage, working-set, gc-pause-ms    (tín hiệu quá tải)
//   - active-connections, queued-requests    (back-pressure Kestrel)

Mọi chương trong series đều trích một trong các tín hiệu này. Chương rate limit chặn QPS; chương observability xuất chúng sang Prometheus; chương circuit breaker phản ứng khi chúng vượt ngưỡng. Biết các từ nghĩa là hiểu các chương ấy làm gì với các từ.

Khi nào bộ từ vựng này không còn hữu ích?

Hai trường hợp.

Một, khi bạn còn ở giai đoạn prototype: cụ thể về p99 là phí công trong khi schema còn đổi mỗi tuần. Dùng trung bình và "thấy nhanh / thấy chậm" cho đến khi traffic là thật.

Hai, cho workload batch / ETL nơi tổng thời gian job quan trọng hơn latency từng request. Báo p99 cho job Spark đêm là sai trục - đúng trục là thời gian jobchi phí mỗi row. Phần lớn service .NET trong series là interactive request/response, nên cách suy nghĩ percentile áp dụng được; chương 23 (analytics events pipeline) là chỗ duy nhất metric batch chiếm ưu thế.

Đi tiếp đâu từ đây?

Chương kế tiếp: ước lượng nhanh back-of-envelope - biến từ điển này thành con số bạn vẽ được trên bảng. Sau đó, CAP và consistency giới thiệu bộ từ vựng thứ hai điều khiển mọi quyết định database trong series.

Câu hỏi thường gặp

Vì sao dùng p99 thay vì latency trung bình?
Trung bình giấu phần đuôi. Service có 99 request 50 ms và 1 request 5000 ms cho trung bình 99 ms - nhìn ổn. Một khách hàng chờ 5 giây sẽ không thấy ổn. p99 nói '1 trong 100 user chờ lâu thế này' - đó là con số làm nổi nỗi đau thật của user. p99.9 bắt loại lỗi gọi oncall lúc nửa đêm.
Khi nào scale up vs scale out?
Scale up (dọc) cho đến khi máy quá tải hoặc khi tier CPU kế tiếp giá 4x cho 2x hiệu năng - trần thường gặp trên một VM. Scale out (ngang) khi workload song song tự nhiên - nhiều request nhỏ, không state chia sẻ - hoặc khi một lỗi không được làm sập cả service. Câu trả lời thực dụng là scale up trước vì rẻ hơn về độ phức tạp code, đến khi QPS buộc tay bạn.
SLA, SLO, SLI khác nhau ra sao?
SLI (indicator) là phép đo - 'tỉ lệ thành công của /checkout trong 5 phút gần nhất'. SLO (objective) là mục tiêu nội bộ - '99.9% trong 30 ngày'. SLA (agreement) là cam kết bên ngoài, thường kèm tiền - 'hoàn 10% nếu uptime tháng dưới 99.5%'. SLA luôn yếu hơn SLO để có khoảng đệm trước khi vi phạm.
Bộ từ vựng này áp dụng cho .NET cụ thể ra sao?
Số đo lấy từ công cụ .NET cụ thể. Kestrel emit p50/p99 qua OpenTelemetry. dotnet-counters cho thấy GC pause làm tăng tail latency. Rate limiter của ASP.NET Core (chương 14) chặn QPS. Command interceptor của EF Core lộ latency query. Mọi chương đều trích các số này - chương này là từ điển.