Архитектура real-time систем: WebSocket, SSE и Long Polling
Архитектура real-time систем: WebSocket, SSE и Long Polling
В современном вебе интерактивность стала стандартом. Пользователи ожидают мгновенных уведомлений в чатах, обновления курсов акций в реальном времени, изменения статусов заказов и плавную анимацию игровых событий. Традиционная модель HTTP «запрос-ответ» (Request-Response) идеально подходит для загрузки страниц или получения данных из БД по запросу, но она не предназначена для ситуаций, когда сервер должен сам «толкать» данные клиенту в момент их появления.
Для решения этой задачи архитекторы используют три основных подхода: Long Polling, Server-Sent Events (SSE) и WebSockets. В этой статье мы разберем технические нюансы каждого метода, их сильные и слабые стороны, а также критерии выбора подходящего решения для вашего проекта.
1. Long Polling: Классика с ограничениями
Long Polling — это техника, имитирующая push-уведомления в рамках стандартного протокола HTTP. Клиент отправляет запрос к серверу, и сервер не отвечает сразу. Он «держит» соединение открытым до тех пор, пока не появятся новые данные или не истечет тайм-аут.
Как только сервер получает данные (или время вышло), он отправляет ответ, и клиент тут же инициирует новый запрос.
Преимущества:
- Поддержка всеми браузерами (даже самыми старыми).
- Работает через стандартные HTTP-прокси и фаерволы.
Недостатки:
- Значительный оверхед: каждый новый запрос требует повторной передачи заголовков (headers), что нагружает сеть при частом обновлении данных.
- Задержка: между получением ответа и отправкой нового запроса есть микрозадержка.
Когда использовать: Сегодня Long Polling используется редко, в основном как fallback-метод для старых систем или когда обновления происходят редко (например, раз в несколько минут).
2. Server-Sent Events (SSE): Эффективный односторонний поток
SSE — это стандарт, позволяющий серверу удерживать HTTP-соединение открытым и транслировать данные клиенту в виде потока данных. В отличие от Long Polling, здесь не нужно постоянно создавать новые запросы.
Протокол очень прост: сервер устанавливает заголовок Content-Type: text/event-stream и отправляет текстовые сообщения в формате data: сообщение\n\n.
// Пример обработки SSE на Node.js (упрощенно)
app.get('/events', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// Отправка данных клиенту по мере их появления
setInterval(() => {
res.write(`data: ${JSON.stringify({ message: 'Новое уведомление' })}\n\n`);
}, 5000);
});