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, който автоматично анализира потока и генерира събития.

Според данни на CanIUse (2025), EventSource API се поддържа в 97,5% от браузърите глобално. Не се поддържа в Internet Explorer и някои мобилни браузъри (Samsung Internet до версия 7.0). За тези случаи съществуват polyfill-и, които емулират 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 на сървърния endpoint. Браузърът изпраща GET заявка със заглавка Accept: text/event-stream. Сървърът отговаря със статус 200 OK и заглавка Content-Type: text/event-stream, след което започва да изпраща данни във формат event-stream. Връзката остава отворена, докато сървърът не изпрати сигнал за прекратяване или клиентът не извика close().

От страна на сървъра данните се изпращат на части (chunked transfer encoding). Всеки блок данни е текстово съобщение, състоящо се от редове с полета (event, data, id, retry). Сървърът може да изпраща съобщения по всяко време, което прави SSE идеален за известия и актуализации на състоянието. Връзката не изисква постоянен обмен на heartbeat пакети (като WebSocket), въпреки че полето retry контролира честотата на повторно свързване.

Според данни от тестове за производителност (2024), SSE осигурява пропускателна способност до 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НеЗакъснение при повторно свързване в ms

Пример за поток 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 на endpoint-а. EventSource автоматично установява връзката, управлява повторното свързване и анализира входящите съобщения в JavaScript събития.

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

Според документацията на MDN (2025), EventSource поддържа CORS и предаване на идентификационни данни (withCredentials). За предаване на персонализирани заглавки или тяло на заявка, EventSource не е подходящ — изисква се ръчна реализация чрез fetch + ReadableStream. EventSource не поддържа двоични данни — само текст и JSON.

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

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

eventSource.addEventListener('open', () => {
    console.log('SSE връзката е отворена');
});

eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log('Получено:', data);
    renderUpdate(data);
});

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

eventSource.addEventListener('error', (error) => {
    console.error('SSE грешка:', error);
    // Автоматично повторно свързване на браузъра
});

// Затваряне на връзката
eventSource.close();

SSE срещу WebSocket: сравнение

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

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

Според данни от сравнителни тестове (2024), на един сървърен процес SSE поддържа 30–50% повече връзки от WebSocket поради по-опростен протокол. Въпреки това, латентността на SSE е по-висока (50–200 ms срещу 10–50 ms за 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: {"време": "${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 ms). При повторно свързване браузърът изпраща заглавка 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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също