Mạng cho lập trình viên
Sê-ri 45 bài về mạng máy tính nhìn từ góc lập trình viên: mỗi phần dựng lại một hiện tượng mạng trong container rồi đo bằng số thật.
45/45 phần đã đăng
Mạng
1
Gửi 1 byte, có 67 byte chạy trên dây — 98,51% là bao bì, và sách vẽ header TCP sai 12 byte
Mỗi gói TCP/IP trên Ethernet gánh khoảng 66 byte header cố định, không đổi dù ruột là 1 byte hay 1448. Với gói nhỏ, header nuốt gần hết băng thông. Đo thật từng byte bằng tcpdump — kèm sự thật header TCP không phải 20 byte như sách vẽ, và cú offload suýt giấu mất gói quan trọng nhất.
02/09/2026
· 8 phút đọc
2
Cùng một IP đích, đổi prefix một chữ số là nó lật từ 'hàng xóm' thành 'người xa lạ' — tôi hỏi thẳng nhân Linux
Subnet mask, chứ không phải bản thân địa chỉ, mới vẽ ra biên mạng con. Cùng một IP có thể trên-link (ARP thẳng) hay ngoài-link (qua router) tùy prefix. Đo thật bằng ip route get, kèm sự thật: nhân KHÔNG cấm gán .0 và .255 — đó chỉ là quy ước.
02/09/2026
· 9 phút đọc
3
Vì sao gói đầu tiên tới một máy hàng xóm luôn chậm hơn — và một IP không ai giữ khiến kết nối 'treo' thay vì báo lỗi
Trước khi gửi khung đầu tiên tới một máy cùng mạng con, máy phải dịch IP sang MAC bằng một vòng ARP tốn ~190 micro giây — hỏi to, đáp riêng, rồi cache. Trả một lần cho mỗi hàng xóm. Đo thật bằng tcpdump, kèm vì sao ping một IP trống lại kẹt ở INCOMPLETE.
02/09/2026
· 9 phút đọc
4
connect() có cảm giác 'kết nối ngay' — bắt gói ra mới thấy nó tốn 3 gói và trọn một RTT trước byte đầu
Mở một kết nối TCP phải trao đổi SYN, SYN-ACK, ACK — ba gói và một vòng khứ hồi trước khi gửi được byte dữ liệu nào. Trên loopback là vài chục micro giây, nhưng qua hai châu lục là 150ms trả cho mỗi kết nối mới. Đo thật bằng tcpdump, kèm vì sao mọi connection pool tồn tại để né đúng cái thuế này.
02/09/2026
· 9 phút đọc
5
Thêm 10% mất gói: TCP giao đủ 100% nhưng đuôi trễ vọt lên 842ms, UDP giữ trễ thấp mà rơi 9%
Mạng hoàn hảo thì TCP và UDP gần như giống hệt nhau — khác biệt chỉ lộ ra khi mất gói. Dưới 10% loss, TCP mua độ tin cậy bằng đuôi trễ gấp gần 2000 lần UDP; UDP mua trễ thấp đều bằng việc chấp nhận mất. Và cái đo bằng trung vị suýt lừa tôi kết luận ngược. Đo thật bằng netem.
02/09/2026
· 9 phút đọc
6
'Một máy mở được 65535 kết nối' — tôi đo ra trần thật chỉ 28232, và con số 65535 che mất điều quan trọng
Một máy khách không mở được 65535 kết nối tới một đích — trần thật là kích thước dải cổng tạm (~28232), và nó đếm theo từng bộ bốn nên đổi cổng đích là nhân đôi hạn ngạch. Cộng thêm sự thật khó chịu: một kết nối vừa đóng vẫn ghim cổng hàng chục giây. Đo thật trong container.
02/09/2026
· 10 phút đọc
7
Đường rơi 10% gói, mà datagram lớn của bạn mất tới 37% — số học tàn nhẫn của phân mảnh IP
Vượt MTU thì gói hoặc bị cắt thành mảnh, hoặc bị chặn thẳng nếu đặt cờ DF (ngưỡng đúng 1472 byte trên MTU 1500). Và mất một mảnh là hỏng cả datagram: 10% mất gói biến thành 37% mất datagram khi cắt 5 mảnh. Đo thật từng byte trong container, kèm cú gắn netem nhầm chỗ.
02/09/2026
· 10 phút đọc
8
Đường gigabit mà tải file bên kia địa cầu vẫn ì ạch vài MB/s — thủ phạm không phải băng thông
Với cửa sổ TCP cố định, thông lượng tỉ lệ nghịch với RTT: RTT gấp đôi thì tốc độ còn một nửa, bất kể băng thông rộng bao nhiêu. Nới cửa sổ gỡ được trần đó (nhanh gấp 40 lần), nhưng RTT vẫn phạt bạn qua slow-start. Đo thật bằng netem, kèm cái bẫy đo-quá-ngắn.
02/09/2026
· 10 phút đọc
9
Vì sao một luồng tải đơn không lấp nổi đường 10 Gbit — và con số vàng để gỡ nút thắt
Ở RTT cố định, thông lượng tăng tuyến tính theo cửa sổ TCP cho tới khi đụng trần băng thông rồi đứng lại. Điểm gãy đúng bằng tích băng thông–độ trễ (BDP). Dưới BDP là phí băng thông, trên BDP là phí RAM — điểm ngọt nằm ngay tại đó. Đo thật, kèm bẫy benchmark trên veth trần giấu mất nửa sự thật.
02/09/2026
· 9 phút đọc
10
99% gói vẫn tới nơi, mà đường ống chỉ chạy 3% công suất — cú sập TCP mà ai cũng nên biết
Chỉ 1% mất gói làm sập thông lượng CUBIC khoảng 30 lần, để 97% băng thông nằm không — vì giao thức đọc mọi gói rơi thành 'đường tắc'. Đường cong sập theo căn bậc hai của tỉ lệ mất gói, nên vài phần trăm đầu tiên hại nặng nhất. Đo thật bằng netem, kèm vì sao BBR ra đời.
02/09/2026
· 10 phút đọc
11
Người nhận không đọc một byte nào, tôi vẫn send() được 1,5 MB — rồi mới hiểu vì sao write() đôi khi đứng khựng
send() nuốt được khoảng 1,5 lần tổng hai đệm socket rồi mới chặn, dù người nhận đứng hình không đọc byte nào. Đó không phải lỗi mà là kiểm soát luồng của TCP tự ghìm người gửi theo người nhận. Đo thật, kèm cú bẫy kernel âm thầm nhân đôi đệm.
02/09/2026
· 9 phút đọc
12
Một lệnh lẽ ra vài chục micro giây kẹt đúng 43ms — thủ phạm là hai tối ưu TCP lịch sự chờ nhau
Nagle và delayed ACK, mỗi cái đều hợp lý khi đứng riêng, gặp nhau tạo một thế chờ chết: một vòng request/response kẹt đúng ~40ms, lặp đi lặp lại. Đo thật con số (43ms so với 0,04ms — chênh gần 900 lần), và vì sao bug này khét tiếng khó tái hiện.
03/09/2026
· 9 phút đọc
13
Nửa Internet khuyên vặt tcp_fin_timeout để 'chữa' TIME_WAIT — tôi đo ra nó chẳng đụng tới con số đó
Bên đóng kết nối trước phải nằm TIME_WAIT đúng 60 giây trên Linux, và tcp_fin_timeout (thứ ai cũng khuyên vặn) KHÔNG chỉnh được nó — vì nó điều khiển một trạng thái khác. Đo thật ai gánh TIME_WAIT, bao lâu, và vì sao nó đặt trần ~470 kết nối/giây tới mỗi đích.
03/09/2026
· 9 phút đọc
14
Đầu kia biến mất im lặng, mặc định TCP mất hơn 2 tiếng mới nhận ra — công thức để xuống vài giây
Một kết nối rảnh có peer chết âm thầm: TCP mặc định mất ~2 giờ 11 phút mới phát hiện. Đặt ba núm keepalive thì xuống đúng IDLE + CNT×INTVL giây — vài giây. Đo thật công thức, kèm một bug 'hai chữ timeout' suýt làm tôi kết luận keepalive không chạy.
03/09/2026
· 9 phút đọc
15
Một lookup lẽ ra 50ms treo thành 6 giây — thủ phạm là truy vấn IPv6 mà getaddrinfo lặng lẽ chờ
Một getaddrinfo gửi HAI truy vấn (A và AAAA) và chờ cả hai; nếu AAAA bị một tường lửa im lặng bỏ rơi, lookup treo ~6 giây dù IPv4 đã sẵn ngay từ mili giây đầu. Cộng thêm sự thật ít ai biết: hệ điều hành không hề cache DNS. Đo thật bằng máy chủ DNS tự dựng.
03/09/2026
· 9 phút đọc
16
'Đổi DNS rồi mà chưa ăn' — tôi đo từng giây để thấy chính xác vì sao, và trễ đúng bao lâu
Một bản ghi DNS được đệm đúng bằng TTL giây rồi mới hỏi lại nguồn; đổi bản ghi ở nguồn chỉ có hiệu lực sau khi bản sao đệm hết hạn — trễ đúng một TTL. Và cái con số TTL bạn đọc từ dig không phải TTL gốc mà là TTL còn lại đang đếm ngược. Đo thật từng giây.
03/09/2026
· 9 phút đọc
17
Vì sao máy chủ root DNS gần như không bao giờ bị hỏi tới, dù cả thế giới tra tên mỗi giây
Một tra cứu nguội đi ba vòng — root, TLD, thẩm quyền, mỗi vòng một khứ hồi (~75ms). Nhưng lần thứ hai 0 vòng, và một tên khác cùng đuôi chỉ 2 vòng vì chuỗi ủy quyền đã đệm. Đó là lý do root/TLD toàn cầu hầu như rảnh rỗi. Đo thật bằng cây DNS ba tầng tự dựng — kèm một bug gắn nhãn suýt qua mặt tôi.
03/09/2026
· 9 phút đọc
18
Một cái GET tưởng là một lần đi mạng — bắt gói ra mới thấy nó tốn 2 vòng và header nặng gấp đôi dữ liệu
Một GET trên kết nối mới tốn 2 vòng khứ hồi (bắt tay + trao đổi), HTTPS lần đầu tới 3; tái dùng kết nối còn 1. Và với thân 40 byte, riêng header response chiếm ~78%. Client tự viết của tôi báo request 72 byte — client kiểu trình duyệt là 524, gấp 7 lần. Đo thật bằng tcpdump.
03/09/2026
· 9 phút đọc
19
Keep-alive cắt 20 request từ 2360ms còn 1195ms — nhưng benchmark trên localhost sẽ bảo bạn nó vô dụng
Tái dùng một kết nối cho 20 request né được 19 lần bắt tay, nhanh gấp đôi trên đường RTT ~55ms (2360ms xuống 1195ms). Nhưng đúng phép đo đó trên localhost chỉ chênh 1ms — vì loopback giấu sạch mọi chi phí tính bằng RTT. Đo thật, và vì sao đừng bao giờ đánh giá keep-alive trên máy mình.
03/09/2026
· 9 phút đọc
20
Content-Length bắt client chờ 530ms mới thấy byte đầu; chunked cho thấy sau 105ms — trừ khi bạn dựng chunked sai
Với nội dung sinh dần, Content-Length buộc server sinh hết rồi mới gửi được (byte đầu ~530ms), còn chunked stream từng khối (~105ms) — nhanh gấp 5 lần tới byte đầu. Nhưng dán đúng header mà vẫn buffer hết thì streaming bốc hơi hoàn toàn. Đo thật, kèm hợp đồng ba bên của streaming.
03/09/2026
· 9 phút đọc
21
gzip ép JSON 20 KB còn 2,3 KB, Brotli còn 1 KB — nhưng nén nhầm thứ lại làm phình thêm và đốt CPU
Văn bản co lại 88-95% nhờ nén, gần như miễn phí. Nhưng nén dữ liệu ngẫu nhiên (ảnh, video đã nén) chỉ phình thêm byte, và nén payload tí xíu còn to hơn bản gốc. Cộng thêm một phép so gzip-vs-Brotli thiếu công bằng suýt lừa tôi. Đo thật cả hai bộ nén ở nhiều mức.
03/09/2026
· 9 phút đọc
22
56 KB co xuống 152 byte nhờ một dòng 304 — trừ khi ETag của bạn tính sai, và nó hỏng không một tiếng kêu
Một lần revalidate với ETag khớp biến response 56 KB thành 152 byte — tiết kiệm hơn 99% băng thông. Nhưng một ETag đổi mỗi lần (bug rất phổ biến) biến mọi 304 thành 200, đốt lại toàn bộ băng thông mà trang vẫn chạy đúng, test vẫn xanh, không lỗi nào báo. Đo thật bằng byte trên dây.
03/09/2026
· 8 phút đọc
23
Tải 100MB rớt mạng ở 90% — Range request cho tải nốt 10MB thay vì làm lại, nhưng coi chừng lệch một byte
Xin bytes=30000- để tải tiếp chỉ lấy 70 KB còn lại thay vì cả 100 KB; xin một khúc giữa chỉ lấy 100 byte. Nhưng khoảng byte của HTTP bao gồm cả hai đầu còn lát cắt Python thì không — trộn lẫn là mỗi tệp thiếu đúng một byte và hỏng âm thầm. Đo thật, kèm cái bẫy off-by-one kinh điển.
03/09/2026
· 9 phút đọc
24
20 request: HTTP/1.1 nối đuôi mất 3,4 giây, HTTP/2 một kết nối chỉ 249 ms — và điểm yếu tôi định phô lại trốn mất
HTTP/2 ghép 20 request thành 20 luồng song song trên MỘT kết nối, xong trong 249ms; HTTP/1.1 sáu kết nối mất 823ms, một kết nối nối đuôi tận 3396ms. Tôi tự tin phô điểm yếu chặn-đầu-hàng-TCP của HTTP/2 dưới mất gói — nhưng phép đo của tôi sai hình dạng nên nó không hiện. Đo thật.
03/09/2026
· 9 phút đọc
25
HTTP/2 server push nghe hoàn hảo, sao trình duyệt lại khai tử? Tôi đo cả lợi lẫn hại thì hiểu
Với khách mới, push né được một vòng khứ hồi (185 xuống 120ms) — đẹp. Nhưng với khách quay lại đã cache CSS, nó gửi lại nguyên 33 KB thừa để đổi vài mili giây, trong khi đường tuần tự chỉ tốn 72 byte nhờ 304. Vì đa số lưu lượng là khách quay lại, một ý tưởng đẹp lại thua trên thực tế. Đo thật.
03/09/2026
· 8 phút đọc
26
Tôi benchmark HTTP/3 và nó thua HTTP/2 gấp ba — rồi nhận ra mình đang đua Python với nhân Linux
HTTP/3 trên QUIC được cho là bắt tay nhanh hơn và chịu mất gói tốt hơn HTTP/2. Tôi đo ra ngược lại: bắt tay 554ms so với 176ms. Nhưng cái sai không nằm ở giao thức — nó nằm ở việc tôi so một thư viện QUIC thuần Python với ngăn xếp TCP của nhân. Bài học lớn nhất cả sê-ri về việc công cụ đo có thể lừa chính người đo.
03/09/2026
· 8 phút đọc
27
Tấm ảnh logo của bạn đang cõng theo 147 byte cookie mà nó chẳng bao giờ đọc tới
Mỗi cookie bạn đặt được đính vào MỌI request tới miền — kể cả ảnh và CSS không dùng nó. Một kho cookie 147 byte khiêm tốn nhân với 30 request thành ~4,4 KB tải lên mỗi lần xem trang, và một ngày đẹp trời cookie phình quá trần header có thể làm chết cả trang với đúng một người dùng. Đo thật.
03/09/2026
· 9 phút đọc
28
Mỗi cú chuyển hướng lặng lẽ ăn của bạn một vòng mạng — và POST của bạn có thể bốc hơi trên đường
Mỗi 301/302 thêm một vòng khứ hồi (~60ms) khi tái dùng kết nối, nhưng tới hai vòng nếu đổi host. 301 được cache nên lần sau miễn phí, 302 thì trả mỗi lần. Và một cái bẫy ít ai để ý: 301/302 có thể biến POST thành GET, làm mất sạch dữ liệu — 307/308 mới giữ. Đo thật.
03/09/2026
· 9 phút đọc
29
Thêm một lớp nginx trước backend làm chậm bao nhiêu? Tôi đo ra gần như 0 — nếu đặt đúng chỗ
Ai cũng sợ 'thêm một lớp proxy là thêm độ trễ'. Đo thật: proxy cùng máy backend thêm ~0ms, nhưng khác máy thì cộng đúng một vòng khứ hồi (~29ms). Không có 'phí proxy cố định' — cái giá bằng đúng khoảng cách bạn đặt nó tới backend. Đo bằng nginx.
03/09/2026
· 9 phút đọc
30
Round-robin chia 60 request thành 20/20/20 'hoàn hảo' — và đó chính là cái bẫy
Round-robin chia đều tăm tắp theo lượt, kể cả nhét 20 request cho backend chậm nhất. Least-connections thì chỉ đưa nó 2 request, dồn phần còn lại cho hai máy rảnh. 'Đều' không phải 'cân bằng' — và cái khác biệt đó quyết định 1/N người dùng của bạn có phải chờ máy ốm hay không. Đo thật bằng nginx.
03/09/2026
· 9 phút đọc
31
Bể kết nối 1 chạy 30 request mất 2581ms, bể 30 chỉ 146ms — nhưng to hơn nữa lại vô ích
Kích thước bể kết nối chính là mức song song của client: pool 1 buộc 30 request nối đuôi (2581ms), pool 30 cho chạy song song (146ms) — nhanh gấp 18 lần. Nhưng lợi ích chững hẳn ngay khi đụng sức của backend, và một bể quá cỡ chỉ tốn tài nguyên. Đo thật.
03/09/2026
· 9 phút đọc
32
Ai cũng bảo protobuf nhỏ hơn JSON cả chục lần — tôi đo ra chỉ 2 lần, và cái lợi thật nằm chỗ khác
Cùng một bản ghi, protobuf nhỏ hơn JSON ~2 lần và mã hóa nhanh hơn 7 lần — không phải 'chục lần' như đồn, và gzip còn làm phình một payload nhỏ. Cái lợi thật của gRPC hóa ra không phải vài byte, mà là CPU ở quy mô lớn, hợp đồng lược đồ, và bốn kiểu gọi streaming. Đo thật.
03/09/2026
· 9 phút đọc
33
Giữ 3000 WebSocket mở tốn 45,8 KB mỗi cái — nhưng socket TCP trần chỉ 0,1 KB: đắt gấp 400 lần vì đâu?
Một khung WebSocket gửi 'hi' chỉ tốn 8 byte trên dây. Nhưng giữ 3000 kết nối mở ngốn 45,8 KB mỗi cái trên máy chủ Python — trong khi 3000 socket TCP trần chỉ 0,1 KB. Tôi định đổ tội cho bộ đệm nhân, rồi một phép đo đối chứng lật ngược: cái đắt là runtime, không phải kết nối. Đo thật.
03/09/2026
· 11 phút đọc
34
Mạng 100 Mbps mà web vẫn ì ạch: tôi suýt viết 'băng thông không quan trọng' — rồi một file 5MB bác ngay
Trang 40 tài nguyên nhỏ: qua 10 mbit là thời gian chững ~520ms, nhưng RTT kéo nó tăng tuyến tính. Một file 5MB thì ngược hẳn — gấp đôi băng thông là gần nửa thời gian. Cái nào là nút thắt hoàn toàn tùy hình dạng tải, và một câu châm ngôn nghe rất kêu chỉ đúng một nửa. Đo thật bằng netem.
03/09/2026
· 10 phút đọc
35
Thêm 1% mất gói: trung vị không nhúc nhích, nhưng p99 nhảy từ 32ms lên 264ms
Mất gói không kéo cái trung bình — nó dựng một vách đứng ~200ms ở cái đuôi p99, nơi 1% người dùng xui nhất đang chịu trận mà bảng theo dõi trung bình không hề thấy. Và tôi vào bài chắc mẩm jitter là thủ phạm chính, hóa ra sai. Đo thật bằng netem.
03/09/2026
· 9 phút đọc
36
Tôi dựng lại màn 'bufferbloat' kinh điển để độ trễ nổ tung — nó nhất quyết không chịu nổ
Bóp băng thông xuống 10 mbit thì tc làm chính xác (ra 9 mbit). Nhưng cảnh đệm phình làm ping vọt hàng giây mà tôi định tái hiện lại không xảy ra: TCP đời nay tự ghìm nên đệm 3 MB chỉ đọng 8 gói. Phải flood UDP — một nguồn không biết lùi — mới bơm nó lên 86 gói và làm ping gấp ba. Đo thật.
03/09/2026
· 9 phút đọc
37
Tôi tưởng NAT ném cổng ngẫu nhiên nên P2P vô vọng — đọc bảng conntrack mới biết mình sai
NAT Linux không tung cho bạn cổng ngẫu nhiên: nó GIỮ cổng nguồn 40000 → 40000, dùng cùng một cổng ngoài cho mọi đích, chỉ đổi khi hai máy nội bộ xung đột (→ 42478). Kiểu ánh xạ 'độc lập điểm cuối' này chính là thứ cho gọi video P2P xuyên NAT được. Đo thẳng bằng conntrack.
03/09/2026
· 9 phút đọc
38
Hai server cùng bind cổng 8080 mà không đụng nhau — còn tôi thì hiểu sai 'cổng đã bị chiếm' suốt bao năm
Hai network namespace cùng giữ cổng 8080 sống song song không xung đột; nhưng bind lại trong cùng một vùng thì Errno 98 ngay. Danh tính một socket nghe không phải số cổng, mà là bộ ba (vùng, địa chỉ, cổng) — và đó là toàn bộ lý do trăm container chạy cổng 80 trên một máy. Đo thật.
03/09/2026
· 9 phút đọc
39
Tôi định chứng minh 'xâu cáp không thành mạng' — nó lại chạy, vì Docker đã lén bật một công tắc
veth là sợi cáp ảo nối đúng hai vùng, cầu nối là switch ảo cho nhiều vùng — bộ khung của mạng Docker. Tôi dựng một chuỗi cáp để chứng minh nó không thể thành mạng, rồi ngã ngửa khi nó thông ngay: network namespace thừa kế ip_forward=1 của Docker chứ không phải 0 như máy Linux trần. Đo thật.
03/09/2026
· 9 phút đọc
40
Cùng là 'chặn' mà một luật khiến client treo 2 phút, luật kia từ chối trong 0,1 ms
DROP nuốt gói trong im lặng khiến client treo ~127 giây trên máy mặc định; REJECT từ chối ngay 0,1 ms. Và 10000 luật iptables làm RTT gấp 2,5 lần, còn đúng một luật ipset thì không. Vì sao chọn nhầm giữa hai kiểu 'chặn' là gốc rễ của vô số buổi gỡ lỗi mất hàng giờ. Đo thật.
03/09/2026
· 10 phút đọc
41
Unix socket nhanh gấp mười TCP loopback? Tôi đo ra chỉ 1,6 lần — và cái bẫy Nagle tôi giăng sẵn không sập
Cùng một máy, Unix socket nhanh hơn TCP loopback thật — nhưng chỉ ~1,6 lần độ trễ (18,8 so 30,2 µs), không phải chục lần như tôi tưởng. Và cú treo Nagle 40ms tôi chủ động giăng bẫy để tái hiện lại chẳng thèm xuất hiện. Hai trực giác, hai lần trượt. Đo thật trong container.
03/09/2026
· 9 phút đọc
42
Một lần GET tốn 10 gói tin — mà chỉ 2 gói thật sự chở nội dung
Bắt trọn một luồng TCP của đúng một lần HTTP GET: 10 gói, chỉ 2 chở dữ liệu, 8 gói còn lại là bắt tay + ACK + đóng. Và 'byte ma' của SYN/FIN suýt làm tôi đi tìm một lỗi không hề tồn tại. Đọc từng gói bằng tcpdump.
03/09/2026
· 9 phút đọc
43
Hạ tcp_fin_timeout để 'dọn' TIME-WAIT — lời khuyên nhan nhản trên diễn đàn mà tôi đo ra là sai
Đọc vòng đời một kết nối TCP qua ss: LISTEN, ESTABLISHED, TIME-WAIT, CLOSE-WAIT. Tôi hạ tcp_fin_timeout để rút TIME-WAIT như lời khuyên phổ biến — nó chẳng nhúc nhích, vì nó chỉnh một trạng thái KHÁC. Và TIME-WAIT với CLOSE-WAIT: hai bệnh cùng chữ 'wait' nhưng chẩn đoán ngược nhau. Đo thật.
03/09/2026
· 9 phút đọc
44
Exponential backoff mà ai cũng khoe chỉ làm nửa việc — 50 client vẫn dập server thành từng đợt 50 gói đồng bộ
Thử lại ngay dội 2000 request vào một server chỉ lỗi 2 giây, đủ giết nó. Tôi tưởng exponential backoff là đủ. Nhưng backoff KHÔNG jitter vẫn khiến 50 client thử lại thành từng đợt ~50 gói đồng bộ ở giây 1, 2, 4, 8 — jitter mới tãi chúng ra mượt. Đo thật với 50 client.
03/09/2026
· 9 phút đọc
45
Một chặng chậm thêm 100ms đẩy tổng song song lên đúng 172ms — bằng kẻ chậm nhất, không phải tổng
Bốn chặng gọi tuần tự tốn 261ms; song song hoá còn 63ms. Nhưng một chặng chậm +100ms đẩy tổng song song lên 172ms — bằng chặng chậm nhất, không phải tổng. Và lần đầu đo, mỗi chặng cõng thêm 40ms lạ mà thủ phạm là chính cái máy chủ tôi tự dựng kẹt Nagle. Bài cuối của sê-ri. Đo thật.
03/09/2026
· 8 phút đọc