WebSockets и SSE
1) Қысқаша: не және не үшін
WebSocket (WS/WSS) - толық дуплексті арнаға дейінгі HTTP-қосылысты жаңарту. Чат, live-ойындар, коллаборация, екі бағытты телеметрия үшін қолайлы.
Server-Sent Events (SSE) - серверден шолғышқа біржақты стрим (MIME 'text/event-stream'). Тикерлер, хабарламалар, баға белгілеулер, тапсырмалар прогресі үшін тамаша. Клиент - 'EventSource'.
- Клиенттен нақты уақыт режимінде енгізу қажет (жиі және көп) → WebSocket.
- Тек серверден іске қосу жаңартулары, үйлесімділік және қарапайымдылық → SSE маңыздырақ.
2) Желі және хаттамалар
2. 1 Көлік және үйлесімділік
WebSocket: HTTP 'GET... Upgrade: websocket` (HTTP/1. 1). HTTP/2 үшін RFC 8441 (CONNECT + ': protocol = websocket') болуы мүмкін, қолдау проксиден тәуелді. TLS (WSS) үстінде жұмыс істейді - сынамада міндетті түрде.
SSE: ағыны бар әдеттегі ұзақ HTTP жауабы ('200 OK'). HTTP/1 арқылы өте жақсы жүреді. 1/2/3, CDN/проксидермен үйлесімді (егер ұзын коннектілер үзілмесе).
2. 2 Прокси/теңгерімдегіштер/CDN
Тексеріңіз: ұзақ өмір сүретін қосылымдарды, IDL және таймауттарды, sticky-сессияларды (егер тораптағы жағдай болса) қолдайды.
WS үшін: 'proxy _ read _ timeout', 'upgrade' - тұтқаларын, пер-қосылу лимиттерін қосыңыз.
SSE үшін: прокси жауап бермейтініне көз жеткізіңіз (әйтпесе клиент оқиғаларды уақытында көрмейді).
3) Хабарлама моделі және ағынды басқару
WebSocket: мәтін немесе екілік кадрлары; 'ping/pong' бар, бірақ орнатылған backpressure жоқ - бағдарламада (кезек, терезе, drop-policy) іске асырыңыз.
SSE: мәтіндік оқиғалар (UTF-8); клиент кідіріспен reconnect жасай алады; сервер 'retry:' деп тапсыра алады. Қажетті позициядан жаңарту үшін 'id:' және 'Last-Event-ID' тақырыбы бар.
- per-клиент шығыс хабарларын квоталаңыз.
- Жіберілмеген оқиғалар кезегін шектеңіз; толу кезінде - басымдылығы төмен лақтыру/агрегаттау.
- WS үшін: «жылжымалы терезені» және бағдарлама деңгейіндегі ACK схемасын пайдаланыңыз.
4) Қосылыстардың сенімділігі
4. 1 Детекция және keepalive
WS: әрбір N секунд сайын 'ping' жіберіңіз; таймаут бойынша үзілім - экспоненциалды backoff + джиттермен reconnect.
SSE: сервер «аңғартпаларды» ':\n' heartbeat ретінде жібереді; клиент өзі қайта қосылады.
4. 2 Ағынды қалпына келтіру
WS: offset/sequence хабарларын сақтаңыз және reconnect кейін дельтаны сұраңыз.
SSE: 'id:' дегенді әрбір оқиға үшін және 'Last-Event-ID' дегенді сұрауда пайдаланыңыз - сервер жіберілген оқиғаларды жібереді.
5) Аутентификация және авторизация
Сұрау URL-дегі (WS) JWT Bearer қауіпсіз емес. Тақырыпты (бастапқы HTTP хэндшейк арқылы) немесе 'Secure', 'HttpOnly', 'SameSite' жалаушалары бар кукилерді пайдаланыңыз.
mTLS (әсіресе B2B үшін), сондай-ақ бастапқы сұрау үстіндегі қолтаңбалар (HMAC) болуы мүмкін.
Куколары бар SSE үшін CORS ('Access-Control-Allow-Origin', 'Allow-Credentials') туралы есте сақтаңыз.
Токеннің ротациясы: ағынды үзбеңіз. «Жақында аяқталады» деп хабарлаңыз → клиент жаңа токенмен қосылымды қайта ашады.
6) Деректер форматы және компрессия
WebSocket: permessage-deflate сақтықпен қосыңыз (CPU); қысылған форматтарды (Proto, Euro) қысудан аулақ болыңыз. Бинарлық payload JSON-ға қарағанда үнемді.
SSE: бұл мәтін; ірі деректер үшін REST/gRPC ресурсына немесе chunk файлдарына сілтеме жіберіңіз; SSE үшін gzip тасымалдау - орынды, бірақ прокси/CDN буферизациясын қадағалаңыз.
7) Масштабтау және фан-аут
7. 1 Көлденең масштабтау
Бағдарламаны қайта іске қосу үшін ақаусыз ұстаңыз. Қосылыстардың жай-күйі - фронт-қабатта; деректер - брокерден.
Жергілікті кезектер болса, Sticky (session/user бойынша хэш) қажет.
Ideal - stateless фронт: торап тек жазылымдарды мультиплексиялайды; оқиғалар ортақ pub/sub.
7. 2 Pub/Sub және брокерлер
Кең фан-аут үшін Kafka/NATS/Redis Streams пайдаланыңыз.
«Fanout Gateway» қабаты топиктерге жазылады және WS/SSE бойынша клиенттерге пушит.
Түйіндер арасындағы жүктемені теңестіру үшін бағыттау кілтін қолданыңыз (мысалы, 'userId', 'matchId').
8) Өндірістік конфигалар
8. 1 NGINX — WebSocket
nginx map $http_upgrade $connection_upgrade { default upgrade; '' close; }
server {
listen 443 ssl http2;
server_name ws. example. com;
location /ws {
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1. 1;
proxy_read_timeout 75s; # increase for long sessions proxy_send_timeout 15s;
proxy_pass http://ws-backend;
}
}
8. 2 NGINX - SSE (буферлеуді өшіру маңызды)
nginx location /events {
proxy_http_version 1. 1;
proxy_set_header Connection "";
proxy_buffering off; # is critical for proxy_cache off threads;
chunked_transfer_encoding on;
proxy_read_timeout 60m;
proxy_pass http://sse-backend;
}
8. 3 Kubernetes (Ingress Annotations, NGINX Ingress)
yaml metadata:
annotations:
nginx. ingress. kubernetes. io/proxy-read-timeout: "3600"
nginx. ingress. kubernetes. io/proxy-send-timeout: "3600"
nginx. ingress. kubernetes. io/enable-websocket: "true"
nginx. ingress. kubernetes. io/proxy-buffering: "off" # для SSE
9) Кодтың мысалдары
9. 1 SSE клиенті (шолғыш)
js const es = new EventSource("/events? channel=odds", { withCredentials: true });
es. addEventListener("message", (e) => {
const data = JSON. parse(e. data);
renderOdds(data);
});
es. addEventListener("error", () => {
//EventSource will reconnect itself; can be shown spinner
});
9. 2 SSE (Node. js/Express)
js app. get('/events', (req, res) => {
res. writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
});
res. write ('retry: 3000\n\n') ;//3s backoff to client
const sub = subscribe(req. query. channel, (event) => {
res. write(`id: ${event. id}\n`);
res. write(`event: message\n`);
res. write(`data: ${JSON. stringify(event. payload)}\n\n`);
});
req. on('close', () => sub. unsubscribe());
});
9. 3 WebSocket клиенті (шолғыш)
js const ws = new WebSocket("wss://ws. example. com/ws");
ws. onopen = () => ws. send(JSON. stringify({ type: "join", room: "chat-1" }));
ws. onmessage = (m) => handle(JSON. parse(m. data));
ws. onclose = () => scheduleReconnect();
10) Қауіпсіздік және лимиттеу
Rate limiting per-қосылым және per-пайдаланушы: кіріс хабарламаларының жиілігін (WS) және шығыс ағынының жылдамдығын (WS/SSE) шектеңіз.
Қосылымның өмір сүру уақыты және жиынтық трафик бойынша Quota.
Message size limit и max messages/sec.
Хендшейк кезеңіндегі WAF/бот-сүзгілер; connection flooding қорғанысы (көптеген қысқа коннектілер).
tenant/namespace бойынша оқшаулау: жеке ресурстар пулы.
11) Бақылау
Өлшемдері:- `connections_active`, `connections_new_total`, `bytes_in/out`,
- `messages_in/out_total`, `dropped_messages_total`,
- `reconnects_total`, `latency_delivery_ms{p50,p95,p99}`.
- Логи: IP/UA, userId/tenantId, жабылу себебі ('close _ code'), ұзақтығы.
- Трейсинг: оқиғаларды бастапқы командамен байланыстыру (корреляциялық ID); WS үшін батам бойынша «виртуалды» спандарды пайдаланыңыз.
12) Пайдалану нюанстары
TLS-терминациясы клиентке жақын (CDN/edge).
Деплоялар кезінде қосылыстарды (graceful) белсенді ротациялау: жалаушаны «қайта қосыңыз» деп беріңіз.
«Ыстық» арналарды біркелкі тарату үшін кілт бойынша шардалау.
Кеш жазылушылардың күйін түсіру (snapshot + delta).
Соңғы мәндегі кэш (әсіресе SSE) - «салқын» клиент үшін пайдалы.
13) Қарсы үлгілер
SSE немесе JSON арқылы WS арқылы үлкен бинарлық бөліктерді ағызу - HTTP арқылы жүктеуді және хабардағы сілтемені пайдаланыңыз.
Қосылу сәтінде ғана авторизациялау және ұзақ сессияларда қайта тексерудің болмауы.
Қажеттіліксіз жаһандық sticky → теңгерімсіздік және «ыстық» түйіндер.
Ажыратылған таймауттар/лимиттер → қатып қалған коннектілер пулды жейді.
SSE прокси/CDN → «нақты уақыт» буферлеу кідіріс минутына айналады.
reconnect клиентінен кейін sequence/offset → болмауы деректер тұтастығын жоғалтады.
14) Енгізу чек-парағы
- Таңдалған үлгі: WS (екі жақты) немесе SSE (бір жақты).
- Таймауттар, keepalive және reconnect (backoff + джиттер) теңшелген.
- sequence/offset және (SSE үшін) 'id '/' Last-Event-ID' жобаланған.
- Лимиттер анықталған: өлшемі/жылдамдығы/қосылыстары/квоталары, DoS-тен қорғау.
- прокси/ингресс: upgrade, off (SSE), read/send timeouts.
- Масштабтау: pub/sub-брокер, фан-аут-шлюз, sticky қажет болғанда ғана.
- Аутентификация: токенді қауіпсіз беру, үзіліссіз ротациялау.
- Бақылануы: метрика, логия, трасса; дашбордтар мен алерттар.
- Релиздер жоспары: graceful-drain қосылымдары, клиентке қайта қосылу туралы сигнал.
- Game Days: желінің үзілуі, түйіннің құлауы, брокердің артық жүктемесі, ұзын RTT.
15) FAQ
SSE CDN арқылы кэштеуге бола ма?
Әдетте жоқ: бұл дербестендірілген ағын. Көпшілік арналар үшін - қысқа TTL және chunked-delivery болуы мүмкін, бірақ «нақты уақытты» бұзуға оңай.
WebSocket HTTP/2/3 үстінде жұмыс істей ме?
WS браузері HTTP/1 басталады. 1-upgrade; h2 үшін RFC 8441 бар, прокси/серверде қолдау жеке қажет. С h3 - қозғалыста; h3 стримингі үшін WebTransport бар, бірақ бұл басқа API.
gRPC vs WS шолғыш үшін?
Таза браузер gRPC дегенді айтпайды; gRPC-Web Envoy арқылы қажет. Интерактивті UI үшін көбінесе WS + REST оңай.
16) Қорытынды
WebSocket - нақты уақыт диалогы мен ықшам екі бағытты арна қажет болғанда.
SSE - серверден клиентке қарапайым және сенімді push қажет болғанда, ең аз қиындық және автоматты reconnect.
Азық-түліктегі табыс - бұл дұрыс таймауттар мен лимиттер, offset, pub/sub-фан-ауттан қалпына келтіру, проксиді дұрыс баптау және айқын бақылау.