Bài viết mới nhất

Tổng 2300 bài
Lập trình 22/09/2026 7 phút

Histogram và percentile: vì sao latency trung bình 45ms là lời nói dối, và p99 mới là sự thật

Sếp hỏi 'API nhanh không?', bạn trả lời 'trung bình 45ms'. Cả hai đều sai lầm — vì không ai trải nghiệm cái trung bình đó. Bài này đo thật trên 100.000 mẫu latency lệch: mean 44.9ms nhưng p50 chỉ 15.3ms và p99 tới 725ms — trung bình rơi vào khoảng trống không ai gặp. Kèm cách dựng histogram kiểu Prometheus để ước lượng percentile với O(1) bộ nhớ, và đo thẳng sai số của nó (p95 lệch tới -34%).

Lập trình 22/09/2026 7 phút

Prometheus client trong Go: expose /metrics, đọc định dạng exposition, và hiểu mô hình pull

expvar cho counter/gauge nhưng thiếu label và histogram — production cần nhiều hơn. Bài này đo thật với thư viện Prometheus client_golang: khai CounterVec (label method/status) và HistogramVec, tung 1000 request, rồi curl /metrics đọc output thật. Xem histogram tự sinh _bucket{le=...}/_sum/_count ra sao, kiểm số liệu khớp tải bằng grep, và hiểu vì sao Prometheus scrape (pull) thay vì nhận push.

Lập trình 22/09/2026 7 phút

RED và USE: hai phương pháp chọn đúng metric, để khỏi đo tràn lan mà vẫn mù lúc sự cố

Có công cụ metric rồi, câu hỏi khó hơn là ĐO CÁI GÌ. Đo tràn lan làm loãng tín hiệu và nổ cardinality; đo thiếu thì mù lúc sự cố. Hai phương pháp luận cắt gọn: RED (Rate, Errors, Duration) cho service, USE (Utilization, Saturation, Errors) cho tài nguyên. Bài này đo thật một service worker-pool ở tải thấp và tải cao: RED cho thấy lỗi nhảy từ 1.5% lên 6.9%, còn USE chỉ đúng nguyên nhân — pool utilization 100%, queue dồn tới 18, 103 request bị từ chối.

Lập trình 22/09/2026 6 phút

Distributed tracing: metric nói 'request chậm 39ms', tracing chỉ đúng dbQuery mới là thủ phạm 80%

Metric cho biết một request chậm, nhưng không nói chậm ở CHẶNG nào. Tracing giải quyết điều đó bằng span lồng nhau: mỗi chặng một span, tất cả cùng traceID, mỗi span trỏ về cha để dựng lại cây. Bài này tự cài một tracer tối giản trong Go (không cần backend) và đo thật một request đi qua handler → auth → db → cache: cây span cho thấy dbQuery chiếm 31/39ms = 80%, đúng chặng cần tối ưu.

Lập trình 22/09/2026 7 phút

pprof: đừng đoán hàm nào chậm, đo — CPU profile và heap profile tìm đúng thủ phạm

Tracing chỉ ra chặng nào chậm; nhưng trong một chặng, HÀM nào ngốn CPU hay giữ RAM? Đừng đoán — pprof của Go đo trực tiếp. Bài này chạy thật runtime/pprof: CPU profile chỉ ra main.hotHash chiếm 100% CPU (qua sha256), heap profile chỉ ra main.allocBig giữ đúng 197.76MB còn allocSmall biến mất vì đã bị GC. Kèm cách đọc hai cột flat vs cum mà nhiều người nhầm.

Lập trình 22/09/2026 6 phút

runtime/metrics: quan sát goroutine, heap và GC từ bên trong app Go — bắt rò rỉ goroutine tại chỗ

Metric ứng dụng (phần 3-6) cho biết dịch vụ thế nào, nhưng runtime Go bên dưới cũng cần quan sát: bao nhiêu goroutine đang sống, heap lớn bao nhiêu, GC chạy mấy lần và dừng thế giới bao lâu. Bài này đo thật bằng gói runtime/metrics: sinh 5000 goroutine + cấp phát 1.3GB, thấy goroutines 1→5001, 27 lần GC, 0.70ms STW; rồi thả ra thấy goroutines về 1 — chính là cách bắt rò rỉ goroutine, một trong những lỗi Go nguy hiểm nhất.