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

Connection pool: vì sao pool mặc định 2 làm bạn mở 546 kết nối cho 2000 request

Keep-alive tái dùng một kết nối cho các request tuần tự, nhưng khi nhiều request chạy song song, mỗi luồng cần một kết nối cùng lúc — đó là việc của connection pool. Bài này chạy thật trong Go: 2000 request song song 50 luồng với pool mặc định (2) mở tới 546 kết nối vì churn, còn pool đủ lớn chỉ mở 50 và nhanh hơn. Giải thích cách chọn kích cỡ pool đúng.

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

TLS handshake: cái giá thật của HTTPS đo được, và session resumption cắt nó ra sao

HTTPS an toàn nhưng không miễn phí: sau bắt tay TCP, TLS thêm một bắt tay riêng tốn CPU (toán khóa công khai) và một RTT. Bài này chạy thật trong Go với self-signed cert: TLS full handshake tốn 391µs so với TCP thường 23µs — thêm ~368µs, phần lớn là CPU. Session resumption (500/500 kết nối resumed) bỏ phần đắt; giải thích vì sao trên localhost nó chỉ nhanh 1,1 lần còn trên mạng thực tiết kiệm cả một RTT.

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

DNS resolution: chuyến đi mạng ẩn xảy ra trước cả bắt tay TCP

Trước khi net.Dial kịp bắt tay TCP, có một bước vô hình phải xong: phân giải tên miền thành IP. Bài này chạy thật trong Go: DNS cold tốn 6,97ms (có lúc vọt lên 140ms), cached chỉ 794µs (~9 lần nhanh hơn), còn /etc/hosts thì 1µs không đi mạng. Và httptrace tách được DNS chiếm bao nhiêu trong một request — vì sao DNS chậm/timeout là nguyên nhân 'app chậm' hay bị bỏ sót.

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

Trạng thái socket TCP: đọc /proc/net/tcp để phân biệt TIME_WAIT bình thường với CLOSE_WAIT là bug

Một kết nối TCP đi qua nhiều trạng thái, và hai trong số đó hay gây sự cố: TIME_WAIT và CLOSE_WAIT. Bài này chạy thật trong Go đọc /proc/net/tcp: mở 3000 kết nối ngắn để lại 3091 TIME_WAIT (ăn cổng cục bộ), còn server quên gọi Close để lại đúng 200 CLOSE_WAIT (rò rỉ fd). Giải thích vì sao TIME_WAIT là bình thường còn CLOSE_WAIT tăng không giảm luôn là bug.

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

Băng thông vs độ trễ: vì sao đường 'nhanh' vẫn có thể truyền chậm

Băng thông và độ trễ là hai đại lượng khác nhau nhưng hay bị gộp làm 'nhanh'. Bài này chạy thật trong Go: đo throughput 10,5 GB/s và RTT 3µs riêng biệt, tính Bandwidth-Delay Product, và chứng minh cửa sổ nhỏ làm throughput sụt từ 12 GB/s xuống gần 0 — dù băng thông vật lý không đổi. Giải thích vì sao đường dài băng thông cao vẫn chậm nếu cửa sổ nhỏ hơn BDP.

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

HTTP/2 multiplexing: 300 request song song trên đúng một kết nối

HTTP/1.1 chỉ chạy một request tại một thời điểm trên mỗi kết nối (head-of-line blocking), nên phải mở nhiều kết nối để làm việc song song. HTTP/2 đan xen nhiều stream trên một kết nối. Bài này chạy thật trong Go: 300 request song song qua HTTP/2 mở 0 kết nối mới (dùng lại 1 kết nối), còn HTTP/1.1 mở 221 — và HTTP/2 nhanh gấp gần 4 lần. Kèm lý do vì sao vẫn cần HTTP/3.