Real-Time Backend

Socket.IO основы

Цели урока

  • Понять механизм handshake и upgrade в Socket.IO
  • Отличать Namespace от Room и выбирать подходящий уровень изоляции
  • Использовать Acknowledgements для надёжной доставки событий
  • Понимать fallback-стратегию polling и её trade-offs

WhatsApp в 2016 году обслуживал 1 миллиард пользователей командой из 50 инженеров. Основа - протокол с переподключением, acknowledgements и мультиплексированием. Socket.IO предоставляет всё это из коробки за 5 строк кода.

  • **Slack** - Namespace для workspace, Rooms для каналов, Ack для гарантии доставки
  • **Figma** - real-time collaboration: каждый документ - отдельная Room в Socket.IO
  • **Trello** - live updates с fallback на polling для корпоративных клиентов за прокси

Socket.IO: handshake и upgrade

Браузер открывает вкладку чата и хочет получать сообщения в реальном времени. HTTP - это запрос-ответ: сервер не может ничего отправить первым. **Socket.IO** решает проблему в три шага: сначала устанавливает соединение через HTTP long-polling (работает везде), затем пробует сделать **upgrade до WebSocket**, и если upgrade прошёл - переходит на него навсегда.

Первый запрос - это **handshake**: клиент получает `sid` (идентификатор сессии), `pingInterval`, `pingTimeout` и список доступных транспортов. Затем начинается polling, и параллельно клиент делает WebSocket upgrade запрос.

Socket.IO - это **не** просто WebSocket. Поверх него (или polling) добавляется свой протокол: автоматические ping/pong, переподключение при разрыве, acknowledgements и мультиплексирование namespaces.

Socket.IO при подключении начинает с long-polling, а не сразу с WebSocket. Главная причина:

Rooms и Namespaces

В мессенджере тысячи чатов, но пользователь должен получать сообщения только из своих. Socket.IO предлагает два уровня группировки: **Namespace** (разные приложения на одном сервере) и **Room** (группы сокетов внутри namespace).

**Namespace** - это отдельный endpoint: `/chat`, `/admin`, `/notifications`. Разные namespaces изолированы - события из `/chat` не попадают в `/admin`. **Room** - временная группа внутри namespace. Сокет может входить в несколько rooms одновременно, и каждый сокет автоматически входит в персональный room с именем `socket.id`.

Когда лучше использовать отдельный Namespace вместо Room?

Acknowledgements и надёжность

WebSocket - fire-and-forget: отправил пакет, и неизвестно, дошёл ли он. Для чата это катастрофа - пользователь видит галочку «отправлено», а сообщение потерялось. **Acknowledgements** (ack) решают это: отправитель ждёт явного подтверждения от получателя, прежде чем считать событие доставленным.

Ack - это не автоматическая гарантия доставки. Это механизм **подтверждения прикладного уровня**: сервер получил, обработал и вернул результат. Если соединение разрывается до прихода ack - Socket.IO переподключится, но повторной отправки события не будет. Это ответственность приложения.

Для at-least-once гарантии нужна идемпотентная логика: клиент сохраняет событие с уникальным `clientEventId` и повторяет при переподключении; сервер дедуплицирует по этому id.

Acknowledgement в Socket.IO гарантирует, что сообщение:

Fallback: polling транспорт

Корпоративная сеть часто блокирует WebSocket: прокси не понимает `Upgrade: websocket` и обрывает соединение. Socket.IO автоматически откатывается на **HTTP long-polling** - браузер делает GET-запрос, сервер держит его открытым до появления события, затем клиент сразу делает следующий запрос.

Если WebSocket недоступен из-за прокси и нужна минимальная задержка - рассмотрите **Server-Sent Events** для сервер→клиент и HTTP POST для клиент→сервер. SSE проходит через большинство прокси и быстрее polling.

Socket.IO с `transports: ['polling', 'websocket']`. WebSocket заблокирован корпоративным прокси. Результат:

Socket.IO основы

  • Handshake выдаёт sid, начинает с polling, затем upgrade до WebSocket
  • Namespace - изоляция логики и middleware (разные endpoints приложения)
  • Room - динамические группы внутри namespace для targeted broadcast
  • Acknowledgements: callback подтверждает обработку на прикладном уровне
  • Fallback на polling прозрачен для приложения, API не меняется

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

Socket.IO строится поверх WebSocket и решает задачи, которые встречаются во всём real-time стеке.

  • WebSocket протокол — Socket.IO использует WebSocket как основной транспорт, добавляя свой протокол поверх
  • Server-Sent Events — Альтернатива polling транспорту для направления сервер→клиент
  • Socket.IO Advanced — Middleware, binary data, volatile events и Redis Adapter для масштабирования

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

  • Когда имеет смысл отказаться от Socket.IO в пользу нативного WebSocket API?
  • Как реализовать at-least-once доставку поверх acknowledgements при нестабильном соединении?
  • В каких сценариях Namespace предпочтительнее отдельных Socket.IO серверов?

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

  • rt-05 — Socket.IO runs on WebSocket by default; understanding the transport is required
  • rt-08 — Socket.IO serialization choices (JSON + binary) become clear after the serialization lesson
  • rt-10 — Socket.IO advanced features (rooms, namespaces, adapters) build directly on the basics
  • rt-06 — Socket.IO is one of the 'approaches' compared in rt-06; seeing the comparison motivates the library choice
  • net-36-websocket
Socket.IO основы

0

1

Войти