Backend

WebSocket SSE и polling: как выбрать способ обновления данных

WebSocket SSE и polling: как выбрать способ обновления данных

Когда перед разработчиком встает задача сделать интерфейс «живым» — чтобы уведомления прилетали мгновенно, а котировки акций менялись без перезагрузки страницы — первым делом в голову приходят WebSocket или SSE. Но опытный архитектор сначала спросит: «А точно ли нам не хватит обычного опроса по таймеру?».

Выбор технологии обновления данных — это всегда компромисс между UX, нагрузкой на инфраструктуру и сложностью поддержки. В этой статье мы разберем три основных подхода, разберем их «подкапотную» часть и определим, какой инструмент в какой ситуации будет оптимальным.

1. Short Polling: Старый добрый опрос

Short Polling (короткие опросы) — это самый примитивный способ. Клиент просто отправляет HTTP-запрос на сервер через равные промежутки времени (например, раз в 5 секунд): «Есть что-то новое?». Сервер отвечает либо актуальными данными, либо пустым ответом.

Как это работает на практике

Это обычный REST-запрос. Клиент делает GET /api/updates, получает JSON, закрывает соединение. Через $N$ секунд повторяет процедуру.

Плюсы:

  1. Максимальная простота. Не нужно настраивать специфические серверные модули, прокси-серверы или балансировщики.
  2. Отказоустойчивость. Если один запрос упал, следующий просто повторится. Нет состояния «разрыва сессии», которое нужно обрабатывать.
  3. Кэширование. Ответы можно кэшировать на уровне HTTP-прокси или CDN.

Минусы:

    1. Огромный оверхед. Каждый запрос — это полноценный HTTP-пакет с заголовками. Если у вас 10 000 пользователей, которые стучатся раз в секунду, сервер будет тратить больше ресурсов на обработку TCP-хендшейков и парсинг заголовков, чем на полезную работу с базой данных.
    1. Задержка (Latency). Если обновление произошло сразу после запроса, пользователь увидит его только через 4.9 секунды (при интервале в 5с).
    1. Лишняя нагрузка на БД. Сервер будет выполнять тысячи запросов «ни о чем», когда данных на самом деле нет.

2. Long Polling: Эволюция опроса

Long Polling — это попытка сделать опрос более эффективным. Суть в том, что сервер не отвечает сразу, если новых данных нет. Он «придерживает» запрос до тех пор, пока данные не появятся или не выйдет таймаут.

Механика процесса:

  1. Клиент отправляет запрос.
  2. Сервер держит соединение открытым.
  3. Как только в базе появилось обновление, сервер отправляет ответ.
  4. Клиент получает данные и тут же отправляет новый запрос, чтобы снова ждать обновлений.

В чем профит по сравнению с Short Polling?

    • Снижение задержки. Данные приходят почти мгновенно в момент их появления.
    • Меньше пустых ответов. Мы не спамим сервер бессмысленными запросами каждые несколько секунд.

Где начинаются проблемы?

Главная беда Long Polling — управление соединениями. Если у вас тысячи открытых «висящих» запросов, вы быстро упретесь в лимиты по количеству открытых соединений на сервере или в ограничениях веб-сервера (например, лимиты рабочих потоков в Apache).

3. Server-Sent Events (SSE): Односторонний поток

SSE — это стандарт, который позволяет серверу «стримить» данные клиенту по одному HTTP-соединению. Это фактически односторонний канал: сервер пишет, клиент слушает.

Техническая реализация

SSE использует специальный заголовок Content-Type: text/event-stream. Соединение открывается один раз, и сервер может отправлять сообщения в любое время.

Почему SSE часто лучше, чем кажется:

  1. Автоматическое переподключение. Браузер сам пытается восстановить связь, если соединение оборвалось. Вам не нужно писать сложную логику реконнекта вручную.
  2. Легкость. Это обычный HTTP. Вам не нужно менять протоколы, настраивать специфические порты или бороться с особенностями прокси-серверов, которые могут резать WebSocket-трафик.
  3. Экономия ресурсов. Нет постоянных циклов «запрос-ответ». Один раз установили связь — и получаем поток данных.

Ограничения SSE:

    • Только в одну сторону. Клиент не может отправить сообщение через этот же канал. Для этого придется делать обычные POST-запросы.
    • Лимиты браузеров. В старых браузерах (или при использовании HTTP/1.1) есть лимит на количество одновременных соединений с одним доменом (обычно до 6). Если пользователь откроет 6 вкладок с вашим приложением, седьмая просто не загрузится. Решается переходом на HTTP/2.

4. WebSockets: Полноценный двусторонний канал

WebSocket — это полноценный двусторонний (full-duplex) протокол. После «рукопожатия» (Handshake) по HTTP, соединение переключается на протокол ws:// (или wss://), и теперь и клиент, и сервер могут слать данные друг другу в любой момент без лишних заголовков.

Когда это необходимо:

    • Чаты и мессенджеры. Где общение идет в обе стороны с высокой интенсивностью.
    • Коллаборативные редакторы. (Например, Google Docs или Figma), где каждое движение курсора другого пользователя должно быть видно мгновенно.
    • Онлайн-игры. Где задержка в 100 мс может быть критичной.

Обратная сторона медали (Сложности):

  1. Сложность инфраструктуры. Балансировщики нагрузки (Nginx, HAProxy) нужно специально настраивать для поддержки WebSocket.
  2. Stateful-природа. Сервер должен «помнить», какой клиент к нему подключен. Это усложняет горизонтальное масштабирование. Если у вас 3 сервера, и клиент А подключен к серверу 1, а сообщение ему шлет клиент Б через сервер 2, вам понадобится промежуточный слой (например, Redis Pub/Sub), чтобы доставить сообщение.
  3. Здоровье соединения. Вам придется вручную реализовывать Heartbeat (ping/pong), чтобы понимать, что клиент всё еще в сети, а не «отвалился» по таймауту провайдера.

Сравнительная таблица для быстрого выбора

Критерий Short Polling Long Polling SSE WebSockets
Направление Клиент $\rightarrow$ Сервер Клиент $\rightarrow$ Сервер Сервер $\rightarrow$ Клиент Двустороннее
Нагрузка на сеть Очень высокая Средняя Низкая Самая низкая
Реализация Тривиальная Средняя Простая Сложная
Реконнект Не нужен Вручную Автоматически Вручную
Протокол HTTP HTTP HTTP WS / WSS

Итоговый алгоритм выбора (Checklist)

Чтобы не ошибиться с выбором, пройдите по этому списку вопросов:

Нужно ли клиенту отправлять данные так же часто, как получать их?

    • Да $\rightarrow$ Ваш выбор WebSockets.
    • Нет $\rightarrow$ Переходим к вопросу 2.

Обновления происходят редко (раз в несколько минут или часов) и критичность задержки низкая?

    • Да $\rightarrow$ Используйте Short Polling. Это проще всего и надежнее всего в поддержке.
    • Нет $\rightarrow$ Переходим к вопросу 3.

Данные должны приходить мгновенно, но отправка от клиента идет редко (редкие действия)?

    • Да $\rightarrow$ Используйте SSE. Это легче в реализации, чем WebSocket, и работает стабильнее через прокси.
    • Нет (нужна почти мгновенная реакция в обе стороны) $\rightarrow$ WebSockets.

Вы работаете в очень старой инфраструктуре, где запрещены любые соединения, кроме стандартного HTTP?

    • Да $\rightarrow$ Long Polling.

Резюме от автора

Частая ошибка новичков — внедрение WebSockets везде, где только можно. Это создает огромную техническую нагрузку на поддержку и усложняет деплой.

Если вам нужно просто уведомлять пользователя о том, что «заказ готов» или «пришло новое письмо» — SSE будет идеальным выбором. Он дает почти ту же скорость, что и сокеты, но не заставляет вас переписывать всю конфигурацию сервера и бороться с обрывами соединений. Оставляйте WebSockets только для тех случаев, когда вы строите настоящий интерактив в реальном времени.