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

10.000 kết nối WebSocket trên một tiến trình Go đo thật: 27 KB RSS mỗi kết nối idle với bộ đệm mặc định, 20 KB khi hạ xuống 1 KB, ping từng kết nối tốn gấp đôi CPU so với quét, ulimit 1024 gãy ở kết nối 1.018, dải cổng 28.232 cạn vì TIME_WAIT

Server Go nhận 10.000 kết nối WebSocket idle và tự chụp số liệu khi vượt mốc. Bộ đệm gorilla mặc định 4 KB cộng 4 KB: heap 225,7 MB, RSS 277,7 MB, 10.002 goroutine, tức 27 KB mỗi kết nối; hạ xuống 1 KB còn 204,5 MB. Ping mỗi 10 giây: timer riêng từng kết nối tốn 331 MB và 3,75 giây CPU trong 60 giây, quét bằng một goroutine tốn 273 MB và 1,85 giây cho cùng số ping. Ba chỗ gãy: ulimit 1024 dừng ở 1.018 kết nối; bùng nổ 10.000 connect không tràn backlog nhưng p99 tăng từ 45 lên 321 ms; đóng 10.000 rồi mở 20.000 ngay thì TIME_WAIT chiếm trọn 28.231 cổng.

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

Fan-out WebSocket tới 10.000 client đo thật: ghi tuần tự bắt client cuối chờ 91 ms, chia 10 worker còn 31 ms, PreparedMessage bớt 2 ms, một client không đọc làm cả 10.000 client trễ 1,1 giây với ghi tuần tự, 1.000 với shard, không ai với kênh riêng

Server Go phát 40 vòng, mỗi vòng 1 KB tới 10.000 client, ghi timestamp vào payload để client đo độ trễ thật: 400.000 mẫu mỗi cách. Ghi tuần tự: client cuối nhận sau 91 ms, p99 99 ms. Chia 10 worker: 31 ms, p99 43 ms, CPU mỗi vòng tăng từ 90 lên 140 ms. PreparedMessage chỉ giảm 2 đến 3 ms vì ở 1 KB chi phí là syscall chứ không phải copy. Kênh riêng mỗi client: 31 ms nhưng thêm 10.000 goroutine và 52 MB. Lẫn vào một client không đọc với write deadline 1 giây: tuần tự kẹt cả vòng 1.105 ms nên p99 toàn bài thành 1.066 ms, shard kẹt một phần mười số client, kênh riêng không ảnh hưởng ai.

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

Reconnect WebSocket đo thật: rút cáp 3 giây giữa stream 200 sự kiện mỗi giây, cách ngây thơ mất 615 sự kiện không ai biết, seq cộng ring buffer mất 0, session cộng ack mất 0 nhưng trùng 10, và server ghi thành công 411 sự kiện vào kết nối đã chết

Server Go phát 200 sự kiện mỗi giây có số thứ tự, client ReadDeadline 1 giây nối lại mỗi 100 ms, iptables DROP cắt 3 giây. Ngây thơ: mất 615 sự kiện, dải 964 tới 1578, không trùng, không ai biết. Số thứ tự cộng ring buffer 1.000 cộng resume: mất 0, server replay 818. Ring 256 quá nhỏ: server báo gap, client biết mình thiếu 819. Session cộng ack mỗi 50 cộng resend: mất 0, trùng 10, server resend 827 và còn giữ 142 chưa ack. Trong 3 giây đứt, server ghi thành công 1.222 sự kiện vào kết nối cũ nhưng client chỉ nhận 811: 411 biến mất trong kernel.

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

Server-Sent Events đo cạnh WebSocket: Last-Event-ID nối lại mất 0 sự kiện mà không viết dòng client nào, HTTP/2 gom 300 stream vào 2 kết nối TCP, proxy đệm 4 KB giữ sự kiện 6,6 giây, và chiều ngược qua POST tốn gấp đôi một echo WebSocket

Server Go phục vụ SSE qua HTTP/1.1 và h2c, kèm hai proxy và WebSocket echo. Rút cáp 3 giây giữa stream 200 sự kiện mỗi giây: có Last-Event-ID mất 0, không có mất 704, bằng ring buffer tự viết ở phần 8. 100 stream qua HTTP/1.1 là 100 kết nối TCP và 208 goroutine, qua h2c là 1 kết nối và 110 goroutine; 300 stream h2c tự chia 2 kết nối vì Go giới hạn 250 stream mỗi kết nối. ReverseProxy của Go chuyển SSE tức thì, 0,4 ms; proxy đệm 4 KB dồn 68 sự kiện thành một cụm sau 10 giây. POST rồi nhận echo mất 0,112 ms so với 0,064 ms của WebSocket; mỗi sự kiện SSE tốn 28 byte framing so với 2 đến 6 byte.

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

Tổng kết sê-ri WebSocket và realtime đo thật: khung bốn câu hỏi để chọn polling, SSE hay WebSocket, sáu thứ không được bỏ qua dù chọn gì, và checklist vận hành với từng con số đã đo trong 11 phần, từ 27 KB mỗi kết nối tới p99.9 59 ms

Phần cuối gom 11 phần thành khung bốn câu hỏi: dữ liệu đổi bao lâu một lần, chiều lên có dày không, mất một thông điệp thì sao, bao nhiêu kết nối trên bao nhiêu máy. Mỗi nhánh có số đã đo: polling 1 giây 486 ms và 8,4 KB mỗi phút, SSE và WebSocket 0,3 ms và 1,3 KB, 27 KB RSS mỗi kết nối, Redis thêm 0,4 ms, ring buffer 100 KB cho mọi client, session 83 KB mỗi client. Sáu thứ bắt buộc dù chọn gì: write deadline, cô lập goroutine ghi, ping pong, số thứ tự, không cấp phát trong đường nóng, cấu hình proxy. Checklist vận hành ba nhóm: giới hạn hệ thống, timeout và nhịp, chỉ số phải theo dõi.