Содержание

Для функций реального времени — чатов, уведомлений, живых статусов заказов — выбирают между тремя подходами. WebSocket нужен для двусторонней связи с частыми сообщениями, Server-Sent Events — когда данные идут только от сервера к клиенту, а периодический опрос сервера хорош для редких обновлений и самых простых случаев.

Разберём, чем отличаются эти подходы, как масштабировать открытые соединения и какие ошибки встречаются чаще всего.

Какие бывают способы обновлять данные в реальном времени?

Есть три основных способа: клиент регулярно спрашивает сервер (опрос), сервер держит открытый поток и отправляет события (SSE) или клиент и сервер держат двусторонний канал (WebSocket). Выбор зависит от того, кто инициирует сообщения и как часто они приходят.

Подход Направление Когда подходит Сложность
Опрос (polling) Клиент спрашивает сервер Обновления раз в десятки секунд, простые статусы Низкая
Server-Sent Events Сервер → клиент Уведомления, ленты, прогресс задач, ответы AI Средняя
WebSocket В обе стороны Чаты, совместное редактирование, игры, торговля Выше

Когда хватит обычного опроса сервера?

Опроса хватает, когда данные меняются редко, а задержка в 10–30 секунд никого не смущает: статус заявки, количество непрочитанных сообщений, состояние оплаты. Это самый простой вариант — работает через обычный API, кэш и балансировщик без доработок.

Минусы опроса проявляются на масштабе: тысячи клиентов, которые раз в несколько секунд спрашивают «есть ли новое», создают нагрузку, даже когда ничего не происходит. Как спроектировать такие запросы, мы разбирали в статье как спроектировать REST API.

Чем SSE отличается от WebSocket?

Server-Sent Events — это поток событий от сервера по обычному HTTP: браузер сам переподключается при обрыве, а настройка проще. WebSocket — отдельный протокол с двусторонним каналом: он нужен, когда клиент тоже часто отправляет данные и задержка должна быть минимальной.

// SSE: браузер сам переподключится при обрыве
const events = new EventSource('/api/orders/1842/stream')

events.addEventListener('status', (event) => {
  const { status } = JSON.parse(event.data)
  updateOrderStatus(status)
})

SSE отлично подходит для уведомлений, прогресса долгих задач и потоковых ответов языковых моделей. Для чата или совместного редактирования документа удобнее WebSocket.

Человек держит телефон с открытым чатом Фото: Unsplash

Как масштабировать соединения?

Открытые соединения масштабируют отдельным сервером реального времени, а сообщения между экземплярами передают через брокер — например, Redis. Основное приложение публикует событие, сервер реального времени доставляет его всем подписанным клиентам, на каком бы экземпляре они ни были подключены.

Что учесть в архитектуре:

  1. Отдельный сервис для соединений. Долгие соединения не должны занимать процессы, которые обслуживают обычные запросы.
  2. Брокер сообщений. Через него экземпляры узнают о событиях друг друга — подробнее в статье Redis в веб-проекте.
  3. Каналы и авторизация. Пользователь подписывается только на свои каналы, а сервер проверяет права при подписке.
  4. Балансировщик. Он должен поддерживать долгие соединения и правильно их проксировать.
  5. Восстановление после обрыва. Клиент переподключается и запрашивает пропущенные события по последнему идентификатору.

Какие ошибки встречаются чаще всего?

Чаще всего ошибаются, когда считают канал реального времени надёжным хранилищем: соединение может оборваться в любой момент, и сообщение, отправленное в этот момент, потеряется. Источником правды должна оставаться база данных, а канал — только способом быстро сообщить об изменениях.

Типичные ошибки:

  • нет повторной загрузки данных после переподключения — пользователь видит устаревшее состояние;
  • рассылка всем подряд вместо персональных каналов и проверки прав;
  • тяжёлая логика прямо в обработчике соединения вместо очереди;
  • отсутствие ограничений на частоту сообщений от клиента;
  • WebSocket там, где хватило бы опроса раз в 30 секунд.

Коротко

  • Опрос подходит для редких обновлений, SSE — для потока от сервера, WebSocket — для двусторонней связи.
  • SSE проще, работает по обычному HTTP и сам переподключается.
  • Соединения держит отдельный сервис, события между экземплярами передаются через брокер.
  • Канал реального времени — способ доставки, а не хранилище: после обрыва данные догружаются из API.
  • Не усложняйте: начните с самого простого подхода, который решает задачу.

Частые вопросы

  • Можно ли сделать реальное время на PHP?

    Да. Обычно PHP-приложение публикует события, а держит соединения отдельный сервер — например, Laravel Reverb, Centrifugo или облачный сервис. Сам код бизнес-логики остаётся привычным.

  • Сколько соединений выдержит один сервер?

    Специализированный сервер на современном железе держит десятки и сотни тысяч открытых соединений. Ограничением чаще становятся частота сообщений и логика их рассылки, а не количество соединений.

  • Работают ли WebSocket в мобильных приложениях?

    Работают, но только пока приложение открыто. Когда оно свёрнуто, соединение закрывается системой, поэтому важные события дублируют push-уведомлениями.