Real-Time Backend

Socket.IO advanced

Цели урока

  • Реализовать JWT-аутентификацию через Socket.IO middleware
  • Передавать бинарные данные без base64 overhead
  • Отличать volatile от обычных событий и применять в правильных сценариях
  • Настроить Redis Adapter для масштабирования на несколько инстансов

Figma в 2019 году обслуживала миллионы сессий collaborative редактирования. Проблема: позиции курсоров всех участников нужно транслировать в реальном времени, но при 20 пользователях в документе это 20*30 = 600 событий в секунду. Решение - volatile events для курсоров и обычные события для изменений документа. Redis Adapter позволил масштабироваться горизонтально.

  • **Figma** - volatile events для курсоров участников, обычные для операций документа
  • **Socket.IO в Kubernetes** - Redis Adapter стандартен при деплое в несколько pod-ов
  • **Real-time игры** - binary transfer для игрового стейта, volatile для позиций игроков

Socket.IO Middleware и аутентификация

HTTP middleware останавливает неаутентифицированный запрос на входе. В Socket.IO та же логика работает через **middleware** - функцию, которая вызывается при каждом новом подключении до того, как сокет получит первое событие. Это единственное место, где можно проверить JWT, сессию или API-ключ и отклонить соединение.

Middleware можно цеплять в цепочку: первое проверяет JWT, второе проверяет rate limit, третье логирует. Каждое получает тот же `socket` объект и `next`. **Важно**: middleware работает только при установке соединения - для авторизации отдельных событий нужны дополнительные проверки внутри обработчиков.

Namespace middleware выполняется только для сокетов этого namespace. Это позволяет иметь разную авторизацию для `/public` и `/admin` без дублирования логики.

Middleware в Socket.IO вызывается:

Binary данные в Socket.IO

Передача изображения через Socket.IO наивным способом - это base64: изображение 1 МБ становится 1.37 МБ текста. Socket.IO поддерживает нативную передачу **бинарных данных** через `ArrayBuffer` и `Buffer` - без кодирования, с минимальным оверхедом. Socket.IO автоматически детектирует бинарные данные в payload и использует специальный бинарный пакетный тип.

Socket.IO использует специальный формат для бинарных пакетов: объект с `_placeholder: true` для каждого бинарного буфера, затем отдельные бинарные кадры. Это позволяет смешивать JSON-метаданные и бинарные данные в одном событии.

Почему передавать файлы через Socket.IO как Buffer лучше, чем как base64-строку?

Volatile events и буферизация

Координаты курсора в collaborative редакторе отправляются 30 раз в секунду. Если клиент временно недоступен (вкладка в фоне, плохая связь) - буферизовать 300 устаревших позиций бессмысленно: актуальна только последняя. **Volatile events** решают это: если клиент не готов принять событие в данный момент, оно просто отбрасывается.

Какое из событий имеет смысл отправлять как volatile?

Socket.IO Adapters: Redis Adapter

Один Socket.IO сервер держит до ~10 000 соединений. При горизонтальном масштабировании (3 инстанса) возникает проблема: сокет A подключён к инстансу 1, сокет B - к инстансу 2. Вызов `io.to('room-42').emit(...)` на инстансе 1 дойдёт только до сокетов этого инстанса. **Adapter** решает проблему, делая broadcast межпроцессным.

Redis Adapter добавляет задержку ~1-2 мс на каждый broadcast (round-trip через Redis). Для большинства real-time приложений это незаметно. Если это критично - рассмотрите Cluster Adapter для одного хоста или sticky sessions + namespace sharding.

Без Redis Adapter при горизонтальном масштабировании Socket.IO на 3 инстанса `io.to('room').emit()` отправит событие:

Socket.IO advanced

  • Middleware аутентифицирует при connect, результат сохраняется в socket объекте
  • Buffer/ArrayBuffer передаётся нативно без base64, с нулевым overhead
  • Volatile events отбрасываются если клиент не готов - для high-frequency данных
  • Redis Adapter синхронизирует broadcast между инстансами через Pub/Sub
  • Масштабирование: каждый инстанс видит только свои сокеты без adapter

Связанные темы

Advanced функции Socket.IO решают задачи безопасности и масштабирования реального продакшна.

  • Socket.IO основы — Handshake, Rooms, Namespaces и Acknowledgements - фундамент advanced возможностей
  • Redis Pub/Sub — Redis Adapter использует Pub/Sub как транспорт для межпроцессного broadcast
  • Масштабирование WebSocket серверов — Горизонтальное масштабирование Socket.IO через адаптеры и sticky sessions

Вопросы для размышления

  • Как реализовать авторизацию на уровне отдельных событий, а не только при подключении?
  • В каких сценариях Redis Streams Adapter предпочтительнее Redis Pub/Sub Adapter?
  • Как volatile events влияют на UX в collaborative приложениях при плохом соединении?

Связанные уроки

  • rt-09 — Advanced features assume mastery of basic Socket.IO API from rt-09
  • rt-11 — uWebSockets.js vs Socket.IO advanced represents the performance vs developer-experience tradeoff
  • rt-08 — Binary protocol support in Socket.IO advanced connects back to the serialization lesson
  • rt-05 — Knowing WebSocket deeply helps when Socket.IO advanced features (like transport switching) behave unexpectedly
  • net-36-websocket
Socket.IO advanced

0

1

Войти