SSE — что это, Server-Sent Events и односторонний стриминг

Автор: IT Sectr Опубликовано: 2026-06-02 Время чтения: 8 мин

SSE (Server-Sent Events) — стандарт W3C, позволяющий серверу отправлять потоковые данные клиенту через одно HTTP-соединение в одностороннем режиме. В отличие от WebSocket, SSE работает поверх обычного HTTP и не требует специального протокола или библиотеки на стороне клиента. По данным спецификации W3C HTML Living Standard (2025), EventSource API поддерживается во всех современных браузерах, включая Chrome, Firefox, Safari и Edge.

Главное

  • SSE — стандарт односторонней передачи данных от сервера к клиенту через HTTP-соединение.
  • EventSource API — встроенный браузерный интерфейс для приёма SSE без внешних библиотек.
  • Автоматическое переподключение — браузер автоматически восстанавливает соединение при обрыве.
  • Текстовый протокол — данные передаются в формате text/event-stream с простым текстовым форматом.
  • Односторонняя связь — SSE подходит для уведомлений, лент новостей, тикеров и мониторинга, но не для чатов.

Что такое SSE?

SSE (Server-Sent Events) — технология, позволяющая веб-серверу отправлять данные клиенту в любой момент после установления соединения. Она стандартизирована WHATWG как часть HTML Living Standard и использует MIME-тип text/event-stream. SSE поддерживает передачу текстовых данных с возможностью указания идентификатора сообщения, типа события и задержки переподключения.

В отличие от WebSocket, который требует двустороннего протокола и upgrade-запроса, SSE работает поверх обычного HTTP. Сервер устанавливает заголовок Content-Type: text/event-stream, отправляет данные порциями и держит соединение открытым. Клиент получает данные через браузерный EventSource API, который автоматически парсит stream и генерирует события.

По данным CanIUse (2025), EventSource API поддерживается в 97.5% браузеров глобально. Не поддерживается в Internet Explorer и некоторых мобильных браузерах (Samsung Internet до версии 7.0). Для этих случаев существуют полифиллы, эмулирующие EventSource через XHR streaming. SSE не работает с HTTP/1.1 pipelining, но полностью совместим с HTTP/2 server push.

История и стандартизация

SSE был предложен как часть HTML5 спецификации в 2009 году под названием Server-Sent DOM Events. Первая реализация появилась в Opera 9.0, затем в Firefox 6.0 (2011), Chrome 9.0 (2011) и Safari 5.0 (2010). В 2015 году спецификация была выделена в отдельный раздел HTML Living Standard. Несмотря на десятилетнюю историю, SSE остаётся менее популярным, чем WebSocket, из-за односторонней природы.

Как работает SSE

Механизм работы SSE следующий: клиент создаёт экземпляр EventSource с URL серверного эндпоинта. Браузер отправляет GET-запрос с заголовком Accept: text/event-stream. Сервер отвечает статусом 200 OK и заголовком Content-Type: text/event-stream, после чего начинает отправлять данные в формате event-stream. Соединение остаётся открытым, пока сервер не отправит terminate-сигнал или клиент не вызовет close().

На стороне сервера данные отправляются порциями (chunked transfer encoding). Каждый блок данных — это текстовое сообщение, состоящее из строк полей (event, data, id, retry). Сервер может отправлять сообщения в любой момент времени, что делает SSE идеальным для уведомлений и обновлений статуса. Соединение не требует постоянного обмена heartbeat-пакетами (как WebSocket), хотя retry-поле управляет частотой переподключения.

По данным тестов производительности (2024), SSE обеспечивает throughput до 10 000 сообщений в секунду на одно соединение при размере сообщения 256 байт. На стороне сервера каждое SSE-соединение потребляет примерно 5–10 KB памяти, что позволяет одному серверу поддерживать 50 000+ одновременных соединений при 1 GB RAM. Это значительно меньше, чем у WebSocket, из-за отсутствия бинарного протокола.

Формат event-stream

Формат text/event-stream — простой текстовый протокол, где каждое сообщение состоит из именованных полей, разделённых символами новой строки. Каждое поле имеет формат «ИмяПоля: значение». Сообщения разделяются двумя символами новой строки (\n\n).

Поддерживаемые поля: event (тип события, по умолчанию message), data (строка данных, может быть многострочной), id (последний идентификатор события, сохраняется в Last-Event-ID), retry (время переподключения в миллисекундах). Комментарии начинаются с двоеточия (:) и игнорируются парсером, но могут использоваться для heartbeat.

ПолеОбязательноеНазначение
eventНетТип события (message по умолчанию)
dataДаСтрока данных сообщения
idНетИдентификатор события для Last-Event-ID
retryНетЗадержка переподключения в мс

Пример потока event-stream

text
: heartbeat comment
event: update
data: {"user": "Alice", "action": "typing"}
id: 1001

event: notification
data: {"type": "info", "text": "New version available"}
data: {"type": "action", "url": "/upgrade"}
retry: 3000

event: close
data: Session ended

EventSource API на клиенте

EventSource API — встроенный интерфейс браузера для приёма SSE. Для создания соединения достаточно вызвать конструктор с URL эндпоинта. EventSource автоматически устанавливает соединение, обрабатывает переподключение и парсит входящие сообщения в JavaScript-события.

События EventSource: open (соединение установлено), message (получено сообщение без указания event), error (ошибка соединения). Для пользовательских событий (event: custom) можно использовать addEventListener с именем события. EventSource автоматически отправляет заголовок Last-Event-ID при переподключении, что позволяет серверу возобновить поток с прерванного места.

По данным документации MDN (2025), EventSource поддерживает CORS и передачу credentials (withCredentials). Для передачи custom-заголовков или тела запроса EventSource не подходит — требуется ручная реализация через fetch + ReadableStream. EventSource не поддерживает бинарные данные — только текст и JSON.

Клиентский код JavaScript

js
const eventSource = new EventSource('/api/events/stream');

eventSource.addEventListener('open', () => {
    console.log('SSE connection opened');
});

eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log('Received:', data);
    renderUpdate(data);
});

eventSource.addEventListener('notification', (event) => {
    const notification = JSON.parse(event.data);
    showNotification(notification.text);
});

eventSource.addEventListener('error', (error) => {
    console.error('SSE error:', error);
    // Browser auto-reconnects
});

// Close connection
eventSource.close();

SSE vs WebSocket: сравнение

SSE и WebSocket — разные технологии для real-time коммуникации, каждая со своими сильными сторонами. WebSocket подходит для двустороннего обмена данными (чаты, игры, совместное редактирование), SSE — для односторонних потоков от сервера к клиенту (уведомления, ленты новостей, тикеры).

Ключевое различие — WebSocket требует upgrade-запроса с HTTP/1.1 до WebSocket-протокола (ws://), что может блокироваться корпоративными прокси. SSE работает поверх обычного HTTP, проходит через любые прокси и не требует специальной конфигурации сервера. SSE также проще в реализации — серверу не нужна дополнительная библиотека, достаточно правильно сформировать HTTP-ответ.

По данным сравнительного тестирования (2024), на одном серверном процессе SSE поддерживает на 30–50% больше соединений, чем WebSocket, из-за более простого протокола. Однако latency у SSE выше (50–200 мс против 10–50 мс у WebSocket) из-за того, что SSE использует chunked HTTP, а не полноценный двунаправленный поток с бинарными фреймами.

ХарактеристикаSSEWebSocket
НаправлениеСервер → клиентДвустороннее
ПротоколHTTP (text/event-stream)ws:// / wss:// (RFC 6455)
Браузеры97.5% (встроенный EventSource)97% (встроенный WebSocket)
ДанныеТолько текст / JSONТекст + бинарные (Blob, ArrayBuffer)
Обработка проксиПроходит любые проксиТребует настройки прокси
ПереподключениеАвтоматическое (браузер)Ручная реализация
ИсторияLast-Event-IDНет встроенной истории

Как реализовать SSE на сервере

Реализация SSE на сервере не требует библиотек — достаточно установить правильные HTTP-заголовки и отправлять данные в формате text/event-stream. Рассмотрим пример на Node.js с использованием встроенного модуля http. Сервер устанавливает заголовки Content-Type и Cache-Control, после чего отправляет сообщения каждые N секунд.

По данным MDN Web Docs (2025), обязательные заголовки для SSE: Content-Type: text/event-stream, Cache-Control: no-cache и Connection: keep-alive. Без Cache-Control браузер может закешировать SSE-поток, что приведёт к остановке доставки. Connection: keep-alive явно указывает браузеру держать соединение открытым.

Серверный код на Node.js

js
const http = require('http');

http.createServer((req, res) => {
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });

    let eventId = 0;
    const interval = setInterval(() => {
        eventId++;
        res.write(`id: ${eventId}\n`);
        res.write(`event: update\n`);
        res.write(`data: {"time": "${new Date().toISOString()}", "id":${eventId}}\n\n`);
    }, 2000);

    req.on('close', () => {
        clearInterval(interval);
    });
}).listen(3000);

SSE на Python (Flask)

python
from flask import Response, Flask
import time
import json

app = Flask(__name__)

@app.route('/stream')
def stream():
    def generate():
        event_id = 0
        while True:
            event_id += 1
            data = json.dumps(
                {'ticker': 'AAPL', 'price': 150.25})
            yield f'id: {event_id}\nevent: price\ndata: {data}\n\n'
            time.sleep(1)
    return Response(generate(),
        mimetype='text/event-stream')

SSE в мобильных приложениях

Использование SSE в мобильных приложениях ограничено отсутствием нативной реализации EventSource для iOS и Android. На мобильных платформах SSE реализуется через сторонние библиотеки: на iOS — через URLSession с NSURLProtocol, на Android — через OkHttp с SSE-поддержкой (okhttp-sse). Для React Native и Flutter доступны пакеты, эмулирующие EventSource.

На iOS нативная реализация SSE возможна через URLSessionDataDelegate. При получении данных в методе urlSession(_:dataTask:didReceive:) приложение накапливает буфер и парсит event-stream формат вручную. По данным блога iOS-разработки (2024), потребление батареи при SSE на iOS на 40% ниже, чем при постоянном WebSocket-соединении, из-за отсутствия heartbeat-пакетов.

На Android OkHttp предоставляет класс EventSource.Factory для подписки на SSE-потоки. Android-приложения могут использовать SSE для уведомлений, когда FCM недоступен, или для синхронизации данных в фоновом режиме. SSE на Android хорошо работает с WorkManager для долгоживущих фоновых задач. По данным документации OkHttp (2025), okhttp-sse поддерживает автоматическое переподключение с кастомным listener.

Часто задаваемые вопросы

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

SSE — односторонняя передача (сервер → клиент) поверх HTTP, не требует библиотек на клиенте. WebSocket — двусторонняя передача с бинарным протоколом. SSE проще в реализации, WebSocket подходит для задач, где клиент тоже отправляет данные.

Поддерживает ли SSE бинарные данные?

Нет, SSE передаёт только текстовые данные. Для бинарных данных (изображения, аудио) требуется кодировка Base64, которая увеличивает размер на 33%. Для бинарных потоков лучше использовать WebSocket.

Как SSE обрабатывает обрывы соединения?

EventSource автоматически переподключается при обрыве. Время задержки задаётся полем retry в потоке (по умолчанию 1000 мс). При переподключении браузер отправляет заголовок Last-Event-ID, позволяющий серверу восстановить поток с прерванного места.

Сколько соединений SSE может держать браузер?

Каждый браузер имеет ограничение на количество одновременных HTTP-соединений с одним доменом. Для HTTP/1.1 — 6–8 соединений на домен, для HTTP/2 — до 100. SSE использует одно соединение, поэтому конкуренции с другими запросами не возникает.

Можно ли использовать SSE для чата?

SSE подходит только для получения сообщений (входящие). Для отправки сообщений (исходящие) потребуется отдельный HTTP-запрос (POST). Для полноценного чата удобнее использовать WebSocket или Socket.IO с двусторонней связью в одном соединении.

Итоги

  • SSE — стандарт односторонней передачи данных от сервера к клиенту через обычное HTTP-соединение без дополнительных библиотек.
  • EventSource API — встроенный браузерный интерфейс, поддерживаемый 97.5% современных браузеров.
  • Простой текстовый протокол text/event-stream с полями event, data, id и retry.
  • Автоматическое переподключение с поддержкой Last-Event-ID для восстановления потока с прерванного места.
  • Эффективность — SSE поддерживает больше соединений на сервере (50 000+) по сравнению с WebSocket за счёт более простого протокола.
  • На мобильных платформах SSE реализуется через OkHttp (Android) или URLSession (iOS) с ручным парсингом потока.
  • Для односторонних потоков (уведомления, ленты, тикеры) выбирайте SSE, для двусторонней связи — WebSocket или Socket.IO.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также