You've Got (Too Much) Mail: Behind the Scenes of the 3/25/26 Voice Outage
Bài tóm tắt Discord 2026 3. Quy mô lớn Độ khó: Nâng cao
Discord · 2026 · 3. Quy mô lớn · Độ khó: Nâng cao — bài gốc
Bối cảnh
- 25/3/2026, 12:13–15:30 PDT: voice/video suy giảm nặng; user không bắt đầu hay tham gia được cuộc gọi ("Awaiting Endpoint").
- Team Realtime Infrastructure đang chuyển các service Elixir có trạng thái sang Kubernetes. Mỗi host chạy hàng nghìn process trong bộ nhớ (guild, presence, call); trước khi tắt một host phải bàn giao hết process sang node khác.
- Service sessions: mỗi thiết bị đang kết nối có một process session; mọi thứ đẩy xuống client qua websocket đều đi qua nó.
Diễn biến (chuỗi lỗi dây chuyền)
- Thay đổi cấu hình thường lệ: CPU cuối tuần cao, nên team scale dọc pod (tăng CPU/RAM, giảm số pod). Kubernetes cắt 50% pod ở zone đầu tiên. Một bước kiểm tra an toàn bắt chờ các sự kiện đang chạy, nên grace period hết trước khi kịp bàn giao. Kết quả: 17% session toàn Discord bị dừng đột ngột.
- Monitor bùng nổ: mỗi session chết gửi một message
:DOWNtới mọi process đang theo dõi nó. - Gateway: khách được yêu cầu kết nối lại. Rate limit cho việc tạo session chưa được chỉnh lại sau migration (nhiều pod hơn nên giới hạn theo host cho lọt nhiều hơn), làm gateway ở us-east1-b hết RAM, cắt nốt kết nối còn lại trong zone, và tạo thêm một đợt kết nối lại sang zone khác.
- Voice syncers (15 instance điều phối cuộc gọi tới hơn 25.000 SFU):
- hàng loạt cuộc gọi bị dừng rồi tạo lại, tạo ra một cơn lũ kết nối HTTPS đi ra;
- mọi kết nối mới phải qua hai supervisor process đơn luồng (pool Holster và thư viện gun); mỗi supervisor dùng selective receive, nên với hàng đợi 100K message thì mỗi lần spawn chậm thêm ~1ms, và đến một lúc không bao giờ đuổi kịp;
- kết nối etcd dùng cho service discovery cũng đi qua cùng supervisor, nên instance không gia hạn đăng ký được và rơi khỏi hash ring (TTL 60 giây).
- Khôi phục khó:
- restart từng instance thì instance khoẻ lại phải gánh phần dư (làm bản phụ cho instance hỏng), nên hàng đợi đầy lại ngay;
- restart cả cụm thì thundering herd khi khởi động lạnh (tạo lại hàng triệu cuộc gọi);
- rate limit tạo syncer ở các service gọi tới thì lỗi thời hoặc chưa đặt; ở guilds nó chỉ giới hạn syncer "điều phối" mà không giới hạn syncer con của từng kênh.
- Cuối cùng: hạ rate limit, restart từng máy (kiểu "đập chuột"), và gấp đôi cụm (15 instance mới, dựng tay bằng Terraform + Salt vì phần A/V chưa lên Kubernetes). Khoẻ hoàn toàn lúc 14:26.
Thay đổi chính (sau postmortem)
- Admission webhook trên Kubernetes: từ chối scale-down cho tới khi pod bàn giao xong process.
- Thay supervisor của pool bằng PartitionSupervisor (nhiều supervisor độc lập); bỏ hẳn supervisor của gun.
- Chỉnh rate limit phía trên và thêm rate limit cho việc chọn endpoint; có công cụ load shedding.
- Thêm giám sát mailbox của pool kết nối, service discovery, RPC tới SFU. Hướng tới giám sát chung cho các process quan trọng thay vì chỉ số tổng hợp.
- Dài hạn: kiến trúc lại control plane A/V scale ngang qua nhiều region.
Vì sao (bài học Discord tự nêu)
- "Một đợt tải đủ lớn sẽ tìm ra nút thắt trong hệ thống của bạn." Các sự cố trước thì nút thắt là ScyllaDB (sau đó họ thêm circuit breaking tự động ở API); lần này DB ổn, nút thắt dời sang voice.
- Khi gặp giới hạn dung lượng, đó là bài toán kinh tế: hoặc tăng cung (thêm máy), hoặc giảm cầu (rate limit, load shedding). Họ hỏi câu này cả trong lúc xử lý sự cố lẫn trong postmortem.
- Biết rõ công cụ của mình: BEAM cho xem mailbox của từng process (Recon), thậm chí hotpatch.
Bài học cho SWE
- Rate limit phải được chỉnh lại khi topology đổi (VM → nhiều pod hơn). Giới hạn "theo host" thay đổi ý nghĩa khi số host đổi.
- Một process đơn luồng trên đường nóng (supervisor) là nút thắt ẩn; khi nó tắc, các phụ thuộc không liên quan (service discovery) cũng tắc theo. Đây là mặt trái của mô hình actor mà Discord 2017 từng tối ưu.
- Khôi phục cũng có thể gây ra thundering herd: restart từng máy thì máy khoẻ bị quá tải, restart cả cụm thì gặp cold start. Cần giảm cầu trước rồi mới tăng cung.
- Việc migration hạ tầng (Kubernetes) tạo ra các giả định mới (grace period, số pod) phải được kiểm chứng. Xem Deploy và release an toàn.
Liên quan
Hot partition và thundering herdĐộ tin cậy và multi-regionDeploy và release an toànRealtime và fan-outSự cố và postmortemLoad shedding, rate limit và backpressure
Được nhắc tới trong
Chủ đề (6)
Công ty (1)
Bài tóm tắt (4)