Coordinated Omission và Sai lầm Đo lường Latency

Các sai lầm phổ biến nhất khi đo latency trong hệ thống phân tán: bài toán Coordinated Omission, trung bình hóa percentile, và phương pháp load testing chính xác.

coordinated-omissionload-testingmeasurementlatencybenchmarking
Cập nhật: 23 tháng 10, 2026

Tổng quan

Trong bài talk nổi tiếng "How NOT to Measure Latency", Gil Tene đã chỉ ra rằng phần lớn các benchmark và load test đều cho kết quả lạc quan giả tạo (falsely optimistic) do các lỗi đo lường có hệ thống (systematic measurement errors).

Vấn đề không nằm ở tool hay infrastructure — mà nằm ở phương pháp đo. Khi bạn đo sai, mọi quyết định về capacity planning, SLA, và performance tuning đều dựa trên dữ liệu không đáng tin cậy. Hệ thống tưởng chạy tốt ở production, nhưng thực tế đang âm thầm vi phạm SLO mà bạn không hay biết.

Bài viết này tổng hợp ba sai lầm phổ biến nhất: Coordinated Omission, trung bình hóa percentile, và thiếu mẫu thống kê — cùng các phương pháp khắc phục thực tế.

Xem thêm nền tảng về Latency Percentile Metrics và Latency & Throughput Overview trước khi đi sâu vào các sai lầm đo lường.

Coordinated Omission — Bẫy đo lường nguy hiểm nhất

Coordinated Omission là hiện tượng xảy ra khi load test tool vô tình "phối hợp" với server để bỏ sót (omit) các request lẽ ra phải được gửi đi trong khoảng thời gian server bị chậm.

Cơ chế xảy ra

Hầu hết các tool load test (ab, wrk, JMeter mặc định) hoạt động theo mô hình closed-loop: chỉ gửi request tiếp theo sau khi request trước đã nhận response. Khi server gặp GC pause hoặc resource contention và phản hồi chậm, tool tự động giảm tốc độ gửi request.

Kết quả: khoảng thời gian server chậm nhất lại có ít request nhất trong dataset → toàn bộ giai đoạn chậm bị underrepresented trong phân phối latency. P99 đo được sẽ thấp hơn đáng kể so với thực tế.

Đang tải sơ đồ...

Trong ví dụ trên, khi server mất 500ms để xử lý Request 2 (do GC pause), tool đã không gửi ~50 request mà lẽ ra phải gửi (nếu duy trì rate 100 req/s). Những request bị thiếu đó — với latency thực tế rất cao — hoàn toàn biến mất khỏi kết quả đo.

Closed-loop vs Open-loop

Đang tải sơ đồ...

Trong hệ thống production thực tế, user request đến theo open-loop: người dùng không chờ request của người khác hoàn thành rồi mới gửi. Vì vậy, load test cần mô phỏng đúng hành vi này bằng constant-rate loading.

Giải pháp: Constant-Rate Loading

Để tránh Coordinated Omission, cần sử dụng các tool hỗ trợ open-loop model — gửi request theo một schedule cố định bất kể server response nhanh hay chậm.

bash
# wrk2: constant-rate mode (1000 req/s trong 60 giây)
wrk2 -t4 -c100 -d60s -R1000 http://api.example.com

# k6: arrival-rate executor
# config trong k6 script:
export const options = {
  scenarios: {
    constant_load: {
      executor: 'constant-arrival-rate',
      rate: 1000,           // 1000 iterations/s
      timeUnit: '1s',
      duration: '60s',
      preAllocatedVUs: 200,
      maxVUs: 500,
    },
  },
};

export default function() {
  http.get('http://api.example.com');
}

# Gatling: open-model injection
setUp(
  scn.inject(
    constantUsersPerSec(1000).during(60)
  )
)

So sánh các tool

ToolModeCoordinated Omission
ab, wrkClosed-loop❌ Bị ảnh hưởng
wrk2Constant-rate✅ Tránh được
k6 (constant-arrival-rate)Open-loop✅ Tránh được
Gatling (open-model)Open-loop✅ Tránh được
JMeter (Constant Throughput Timer)Semi-open⚠️ Phụ thuộc cấu hình

Lưu ý: wrk2 là phiên bản cải tiến của wrk, được Gil Tene đóng góp phần constant-rate. Flag -R (rate) là điểm khác biệt quan trọng nhất.

Không trung bình hóa Percentile

Một sai lầm cực kỳ phổ biến: tính trung bình của các percentile rồi coi đó là percentile tổng hợp. Cách làm này sai về mặt toán học.

Ví dụ sai lầm

ServerP99
Server A80ms
Server B120ms
Server C300ms

❌ SAI: "P99 trung bình = (80 + 120 + 300) / 3 = 167ms"

✅ ĐÚNG: Merge toàn bộ raw data từ cả 3 server lại, rồi tính P99 trên tập dữ liệu gộp. Giá trị thực có thể cao hơn hoặc thấp hơn 167ms đáng kể — bạn không biết được cho đến khi merge.

Tại sao sai?

Percentile không phải phép đo additive (cộng được). Chúng là order statistic — phụ thuộc vào vị trí trong phân phối, không phải giá trị tuyệt đối. Khi trung bình hóa percentile, bạn mất thông tin về phân phối đuôi (tail distribution) của từng server, và kết quả có thể underestimate hoặc overestimate tail latency thực tế.

Quy tắc vàng: Never average percentiles. Merge first, compute after.

Tìm hiểu thêm tại Latency Percentile Metrics.

Các sai lầm đo lường khác

1. Không đủ samples

Để đo percentile Pxx, bạn cần tối thiểu đủ samples để có ý nghĩa thống kê. P99 với chỉ 50 samples nghĩa là bạn chỉ có 0.5 data point ở tail — kết quả hoàn toàn vô nghĩa.

Khuyến nghị: sử dụng ít nhất 10x so với mức tối thiểu để có kết quả ổn định. Với P99.9, cần ít nhất 10,000 samples — tốt nhất là 100,000+.

2. Đo phía server thay vì phía client

Đo latency ở server-side bỏ qua các thành phần quan trọng mà user thực sự trải nghiệm:

  • Network latency — round-trip giữa client và server
  • Client-side queuing — thời gian request chờ trong connection pool
  • Load balancer processing — thời gian xử lý tại LB/reverse proxy
  • TLS handshake — đặc biệt đáng kể với cold connection

Luôn đo từ phía client (hoặc tốt hơn: từ vị trí gần nhất với end-user) để phản ánh trải nghiệm thực tế.

3. Bỏ qua latency của failed requests

Khi request bị timeout (ví dụ: 30s timeout) hoặc trả về 5xx, latency của chúng thường rất cao nhưng lại bị loại khỏi dataset hoặc ghi nhận là 0ms. Đây là một dạng Coordinated Omission ở mức data processing — bạn đang loại bỏ chính xác những data point tệ nhất.

Quy tắc: Mọi request — kể cả timeout và error — đều phải được tính vào phân phối latency với latency thực tế của chúng.

Xem thêm về tác động ở quy mô lớn tại Tail Latency at Scale.

Checklist Load Test chính xác

Áp dụng checklist sau để đảm bảo kết quả load test phản ánh đúng thực tế:

✓Hạng mụcChi tiết
☐Constant-rate toolSử dụng wrk2, k6 (constant-arrival-rate), hoặc Gatling (open-model)
☐Đủ samples≥1,000 cho P99, ≥10,000 cho P99.9
☐Multi-level loadTest ở 50%, 70%, 90%, 100%, 120% target throughput
☐Latency + Throughput đồng thờiĐo cả hai để xác định saturation point — điểm mà latency bắt đầu tăng phi tuyến
☐So sánh P50 vs P99Nếu gap > 10x → cần điều tra nguyên nhân tail latency (GC, lock contention, noisy neighbor...)
☐Tính cả failed requestsTimeout và 5xx đều phải có trong phân phối latency
☐Đo từ client-sideBao gồm network, queuing, TLS overhead
☐Không average percentileMerge raw data trước, tính percentile sau

Tham khảo thêm: Latency Percentile Metrics | Adaptive Concurrency Control