// Engineering Log

WebSockets, Long Polling и SSE: как работает обмен данными в реальном времени

Опубликовано 22.09.2026

// Быстрый маршрут

Эта статья относится к теме Серверы и инфраструктура.

Чаты, уведомления, биржевые котировки, совместное редактирование, ответы нейросетей, которые появляются по словам, — всё это требует, чтобы сервер передавал данные клиенту сразу, без повторных запросов. HTTP изначально устроен иначе: клиент спрашивает, сервер отвечает. Для обмена в реальном времени поверх него используют три подхода: Long Polling, Server-Sent Events (SSE) и WebSockets.

Long Polling

Long Polling — приём, а не отдельный протокол. Клиент отправляет обычный HTTP-запрос, а сервер не отвечает сразу, а держит запрос открытым, пока не появятся данные или не истечёт время ожидания. Получив ответ, клиент тут же отправляет следующий запрос.

Достоинства:

  • работает везде, где работает HTTP: через любые прокси, межсетевые экраны и старые браузеры;
  • не требует ничего особенного на сервере и в балансировщике.

Недостатки:

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

Сегодня Long Polling используют как запасной вариант, если другие способы недоступны.

Server-Sent Events (SSE)

SSE — стандартный механизм браузера для односторонней передачи событий от сервера к клиенту. Клиент открывает обычное HTTP-соединение, сервер отвечает с типом text/event-stream и не закрывает его, а отправляет события по мере появления.

В браузере для этого есть встроенный объект EventSource:

javascript
const events = new EventSource("/api/events");

events.onmessage = (e) => {
  console.log("Новое событие:", e.data);
};

events.addEventListener("order-status", (e) => {
  console.log("Статус заказа:", e.data);
});

Достоинства:

  • обычный HTTP: не нужен отдельный протокол и особая настройка балансировщика;
  • браузер сам переподключается при обрыве;
  • поддерживаются именованные события.

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

  • только от сервера к клиенту; чтобы отправить данные на сервер, клиент делает обычные запросы;
  • только текст;
  • по HTTP/1.1 браузер держит не больше 6 одновременных соединений с одним доменом, и каждая открытая вкладка с SSE занимает одно из них. По HTTP/2 события идут отдельными потоками одного соединения, и эта проблема исчезает.

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

WebSockets

WebSocket (RFC 6455, 2011) — отдельный протокол с двусторонним обменом по одному постоянному соединению.

Соединение начинается как обычный HTTP-запрос с заголовками Upgrade: websocket и Sec-WebSocket-Key. Сервер отвечает кодом 101 Switching Protocols, и дальше по тому же TCP-соединению обе стороны обмениваются кадрами — текстовыми или двоичными. Адреса имеют вид ws:// (порт 80) и wss:// (порт 443, с TLS). Для проверки соединения протокол предусматривает служебные кадры ping и pong.

Достоинства:

  • обмен в обе стороны без новых запросов;
  • минимальные накладные расходы на сообщение;
  • поддержка двоичных данных.

Особенности:

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

WebSocket поверх HTTP/2

Изначально WebSocket работал только поверх HTTP/1.1. RFC 8441 (сентябрь 2018 года) описывает запуск WebSocket внутри одного потока HTTP/2: сервер объявляет поддержку параметром SETTINGS_ENABLE_CONNECT_PROTOCOL, а клиент открывает поток расширенным методом CONNECT с псевдозаголовком :protocol: websocket. Так WebSocket-соединение и обычные запросы идут по одному TCP-соединению. Работает ли это в вашей связке, зависит от браузера, прокси и приложения — по умолчанию большинство прокси по-прежнему проксируют WebSocket через HTTP/1.1.

Что выбрать

ЗадачаПодход
Уведомления, ленты, прогресс задачи, потоковый ответ сервераSSE
Чат, совместное редактирование, игры, торговые терминалы — данные идут в обе стороны частоWebSocket
Клиенты за строгими корпоративными прокси, старые устройстваLong Polling как запасной вариант
Данные меняются раз в минутыОбычные периодические запросы — проще всех остальных вариантов

Многие библиотеки (например, Socket.IO) сами выбирают лучший доступный транспорт и откатываются на Long Polling, если WebSocket недоступен.

Прокси и балансировщики

Настройки на прокси нужны в двух местах: передача заголовков перехода на WebSocket и тайм-ауты долгих соединений.

  • Nginx. Заголовки Upgrade и Connection не передаются приложению автоматически, их задают явно; по умолчанию nginx закрывает соединение, если в нём 60 секунд нет данных, а для SSE нужно отключить буферизацию ответа. Рабочая конфигурация с блоком map и разбор ошибок — в статье «Прокси-серверы: Часть 2 — Nginx».
  • HAProxy. WebSocket поддерживается без дополнительных модулей, но нужна директива timeout tunnel, иначе соединения закрываются по обычным тайм-аутам. Пример — в статье «Прокси-серверы: Часть 3 — HAProxy».
  • Caddy. Директива reverse_proxy проксирует WebSocket без дополнительной настройки, а ответы с типом text/event-stream отправляет клиенту сразу, без буферизации. При перезагрузке конфигурации WebSocket-соединения по умолчанию закрываются; это поведение меняется параметрами stream_timeout и stream_close_delay.

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

  • Соединение рвётся ровно через минуту. Сработал тайм-аут прокси для неактивных соединений. Поднимите тайм-аут и отправляйте ping из приложения.
  • SSE-события приходят пачкой в конце. Прокси буферизует ответ. Отключите буферизацию для этого адреса.
  • WebSocket работает локально, но не за балансировщиком. Не переданы заголовки Upgrade и Connection, или балансировщик с несколькими серверами разносит запросы одного клиента на разные серверы, а приложение хранит состояние в памяти. Нужна привязка клиента к серверу или общее хранилище состояния.
  • Пропущенные сообщения после переподключения. Протокол этого не гарантирует — приложению нужны идентификаторы сообщений и повторная отправка.

// Похожая задача

Если у вас похожая ситуация

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

Тема статьи

Серверы и инфраструктура

VPS, Linux, веб-стек, миграции, хостинг, базы данных и базовая эксплуатация.

Часто с этим приходят

  • Перенести сайт или сервис на новый сервер
  • Настроить Linux, Nginx, базу данных и бэкапы
  • Разобраться, почему всё работает нестабильно

// Следующий шаг

Если вам нужна не только статья, а помощь по этой теме, удобнее сразу перейти в услугу. Главная и подборка материалов остаются рядом.

Открыть услуги

// Reviews

Отзывы по теме

Спасибо Михаилу за отзывчивость. Созвонились, объяснил как сделать самому. Обращаюсь уже второй раз, все супер и оперативно.

Спасибо Михаилу за отзывчивость. Созвонились, объяснил как сделать самому. Обращаюсь уже второй раз, все супер и оперативно.

kireevk

kireevk

Консультация по nginx proxy manager и portainer

25.02.2025 · ★ 5/5

Освоившийся покупатель
apande

apande

Настройка nginx и opencart

07.09.2024 · ★ 5/5

Очень мощный покупатель
kireevk

kireevk

Диагностика Nginx Proxy Manager в docker контейнере и решение проблемы

15.03.2024 · ★ 5/5

Освоившийся покупатель

// Contact

Нужна помощь?

Свяжись со мной и я помогу решить проблему

Написать в Telegram

Отвечаю в течение рабочего дня (03:00–13:00 GMT)

Или оставьте заявку здесь:

Подтвердите, что вы не бот.

Написать и получить быстрый ответ