Перейти к основному содержимому

Realtime

Изменение попадает на чужие экраны само, без запроса: приходит сообщение, обновляется список, меняется статус. Обычно это WebSockets, иногда server-sent events, изредка — честный polling.

Почему это важно. Realtime легко показать в демо и тяжело эксплуатировать. На мобильном соединение рвётся постоянно: приложение ушло в фон, сменилась сеть, погас экран. Сложность не в том, чтобы доставить сообщение, а в том, чтобы остаться корректным на разрывах.

Что нужно понимать

  • Нужен ли здесь действительно push или хватило бы polling
  • Кто имеет право получать какие сообщения и где это право проверяется
  • Что происходит с сообщениями, отправленными, пока клиент был отключён
  • Как клиент согласует устаревшее локальное состояние с серверным
  • Во что обходится открытое соединение — по батарее и по серверу

Основные темы

Транспорт

  • WebSockets, server-sent events и long polling
  • Переподключение с backoff — чтобы после сбоя клиенты не обрушились на сервер разом
  • Heartbeat и распознавание соединения, которое формально открыто, но мертво
  • Уход в фон и ограничения операционной системы

Каналы и доставка

  • Устройство каналов и топиков, подписка на минимально достаточную область
  • Авторизация подписки — по тем же правилам, что и любое чтение
  • Рассылка одного события множеству подписчиков
  • Гарантии доставки: at most once, at least once — и что у вас на самом деле

Согласованность

  • Догон после переподключения: воспроизвести пропущенное или перезапросить и заменить
  • Порядок сообщений и сообщения, приходящие не по порядку
  • Дедупликация сообщения, доставленного дважды
  • Оптимистичные обновления и откат, когда сервер не согласен

Масштаб

  • Сколько держит один сервер и что меняется, когда серверов два
  • Состояние, которому нельзя жить внутри процесса
  • Push-уведомления для случая, когда приложение не запущено вовсе

Уровни

УровеньКак это выглядит
JuniorПодписывается на поток и обновляет UI, когда приходит сообщение.
MiddleОбрабатывает переподключение, повторную подписку и догон пропущенного. Авторизует подписки и закрывает их за собой.
SeniorПроектирует гранулярность каналов и семантику доставки, рассуждает о порядке и дубликатах, удерживает корректность при нескольких инстансах.

Практика

Для начала

  • Порвите соединение Отключите сеть посреди сессии и добейтесь, чтобы переподключение проходило без перезагрузки.

  • Сузьте подписку Замените широкую подписку на самую узкую из тех, при которых всё ещё работает.

  • Уберите за собой Убедитесь, что уход с экрана завершает его подписку.

Дальше

  • Догоните пропущенное Добейтесь, чтобы за две минуты отключения ничего не потерялось.

  • Обработайте дубликат Сделайте так, чтобы клиент оставался корректным, если одно и то же сообщение придёт дважды.

  • Обновите оптимистично Покажите изменение до подтверждения сервером и аккуратно откатитесь, если он его отклонит.

Проверьте себя

  • Что потеряет ваше приложение, если соединение пропадёт на минуту?
  • Кому разрешено подписываться на каждый канал и где это проверяется?
  • Что будет, если одно и то же сообщение придёт дважды?
  • Сколько открытых соединений держит один инстанс вашего сервера?
  • Что делает приложение, когда возвращается из фона?
  • Какие из ваших realtime-функций спокойно обошлись бы обновлением при открытии экрана?

Материалы

  • WebSockets API — справочник MDN по протоколу и его жизненному циклу, включая коды закрытия: именно на них и строится вся логика переподключения.
  • Serverpod: streams — realtime в Dart-backend: типизированные сообщения, подписки и авторизация.
  • Designing Data-Intensive Applications — главы про потоки и порядок событий. Здешний словарь — at-least-once, идемпотентность, порядок событий — это ровно то, из чего состоят баги realtime.
  • Idempotency keys — прямо применимо к обработке сообщений: единственный надёжный ответ на доставку at-least-once — обработчик, который не ломается от повторного запуска.
  • Firebase Cloud Messaging — для случая, который realtime не покрывает: когда приложение не запущено. Стоит прочитать хотя бы ради раздела о гарантиях доставки.