Сети и протоколы
WebSocket: пережить broadcast-шторм
Читать про backpressure и thundering herd — не то же самое, что вытаскивать real-time-сервис из них. Построй broadcast-сервер, намеренно загони его в оба сбоя и применяй исправления юнита, пока числа не вернутся — с доказательством на каждом шаге.
Преврати ментальную модель юнита в воспроизводимый инженерный цикл: подними WebSocket broadcast-сервер, воспроизведи backpressure-OOM и reconnect-шторм, защитись от каждого через high-water mark и jittered backoff, затем разнеси на два сервера через pub/sub — измеряя до и после.
Построй WebSocket broadcast-сервис (чат или live-лента), намеренно загони его в backpressure-OOM и в thundering herd при переподключении, затем закали его per-connection high-water mark, jittered exponential backoff и Redis pub/sub fan-out — доказывая каждое исправление измерениями до/после под идентичной нагрузкой.
- Таблица до/после для backpressure: total queued bytes, RSS процесса, slow-client count и p99 broadcast-латентность под идентичной нагрузкой — измеренные, не оценённые — показывающая RSS ровным после high-water mark вместо роста к OOM.
- Сравнение до/после для переподключения: SYN/accept rate во времени и время до полного восстановления, показывающее, что версия с jitter размазывает retry по окну и восстанавливается, против синхронной версии, которая застревает.
- Демонстрация, что Origin-проверка отклоняет неавторизованный origin (403), а сообщение сверх лимита отклоняется с close-кодом 1009.
- Короткий разбор, называющий для каждого исправления, какой рычаг из юнита ты использовал (high-water mark, jitter, pub/sub fan-out, sticky sessions) и почему он был самым результативным выбором.
- Добавь message ID плюс Redis stream, чтобы переподключающийся клиент слал свой last-seen ID, а сервер переигрывал только пропущенные сообщения — реализуй at-least-once доставку без дубликатов и докажи это, убив соединение посреди потока.
- Добавь on-call runbook: триаж по пяти панелям, шпаргалка по close-кодам (всплеск 1006 = сетевое событие, 1013 = выселение) и лестница приоритета исправлений.
- Сравни транспорты: реализуй ту же ленту поверх SSE и измерь per-client overhead и поведение переподключения против WebSocket-версии, задокументировав, когда SSE был бы лучшим дефолтом.
- Поставь два сервера за proxy с поддержкой HTTP/2 extended CONNECT (RFC 8441) и измерь экономию kernel-буферов и латентности handshake против HTTP/1.1 Upgrade.
Это цикл, который ты будешь гонять в каждом real-time-инциденте: подними сервис, воспроизведи сбой намеренно, исправь на правильном рычаге (high-water mark для backpressure, jitter для reconnect-стада, pub/sub для межсерверного fan-out, sticky sessions для локальности состояния) и проверь числами до/после под идентичной нагрузкой. Сделав это раз на broadcast-игрушке, превращаешь production-версию — чат масштаба Discord, торговую ленту, совместный редактор — в мышечную память.