WebSocket стримдері мен оқиғалары
TL; DR
Жұмыс ағыны = сенімді арна (WSS) + қорытынды оффсеттер + демпотенттік оқиғалар + қатаң лимиттер және backpressure. Жасаңыз: JWT-аутентификация, топик авторизациясы, heartbeats, seq/offset + resume-токен, at-least-once + дедуп. Масштаб үшін - ақиқат көзі ретінде user/tenant, sticky-роутинг және кезек (Kafka/NATS/Redis Streams) бойынша шардалау.
1) iGaming бизнес-кейстері (нақты ағым)
Баланс/лимиттер: баланстың, RG лимиттерінің, бұғаттаулардың бірден өзгеруі.
Ставкалар/раундтар/нәтижелер: растау, мәртебе, ұтыстарды есептеу.
Турнирлер/көшбасшы борттар: позициялар, таймерлер, жүлделі оқиғалар.
Төлемдер: payout/refund мәртебесі, KYC/AML жалаулары - хабарлама ретінде (ал сын REST + вебхукінде қалады).
Сервистік оқиғалар: сөйлесу хабарламалары, push-баннерлер, сессия мәртебелері, maintenance.
2) Хаттама және қосылу
Тек WSS (TLS 1. 2+/1. 3). Әдепкі құрылғыға/сессияға ең көбі 1 белсенді қосылым.
Ping/Pong: клиент әрбір 20-30 секунд сайын 'ping' жібереді, жауап таймаут 10 с. Сервер қатарынан 3 таймаут кезінде қосылымды тоқтатады.
Компрессия: 'permessage-deflate', кадр өлшеміне арналған лимит (мысалы, ≤ 64 KB).
Пайдалы жүктеме форматы: сыртқы үшін JSON, ішкі/мобильді үшін Protobuf/MsgPack.
3) Аутентификация және авторизация
JWT бар хэндшейк query/header ('Sec-WebSocket-Protocol '/' Authorization'), TTL қысқа (≤ 15 мин), out-of-band бойынша refresh (REST).
Tenant-scoped claims: `sub`, `tenant`, `scopes`, `risk_flags`.
Топиктерге/арналарға ACL: тек рұқсат етілген 'topic' дегенге жазылу (мысалы: 'user: {id}', 'tournament: {id}', 'game: {table}').
Токен біткенде қосылысты қайта құру: «жұмсақ терезе» 60 с.
4) Жазылым үлгісі
Клиент connect командаларын жібереді:json
{ "op":"subscribe", "topics":["user:123", "tournament:456"], "resume_from":"1748852201:987654" }
{ "op":"unsubscribe", "topics":["tournament:456"] }
'resume _ from' - егер клиент қосылуды қалпына келтірсе, оффсет (§ 5 қараңыз).
Сервер ack/nack жауап береді, қатыспаған ACL - 'nack' s 'reason'.
5) Жеткізу кепілдіктері және қорытындылау
Мақсаты: арнаға at-least-once + клиенттің іспеттілігі.
Әрбір оқиғаның «партиясы» (әдетте user/room) аясында монотонды 'seq' және дедуп үшін жаһандық 'event _ id' бар.
Re-коннект кезінде клиент 'resume _ from' = соңғы расталған 'seq' (немесе 'offset' брокеріне) береді. Сервер жіберіп алған оқиғаларды «ақиқат көзінен» (Kafka/NATS/Redis Streams) жүктейді.
Егер лаг retention (мысалы, 24 сағат) асып кетсе, сервер 'snapshot' күйін және жаңа 'seq' күйін жібереді.
- 'last _ seq '/' event _ id' дегенді durable-сақтау орнында (IndexedDB/Keychain) сақтау.
- 'event _ id' дегендегі дедуп, 'seq ≤' дегендегі оқиғаларды өткізіп last_seq', снапшот сұрауының (gap) → авто- 'resync' деген тесіктерін табу.
6) Хабарлама схемасы (envelope)
json
{
"ts": "2025-11-03T12:34:56. 789Z",
"topic": "user:123",
"seq": "1748852201:987654", // partition:offset
"event_id": "01HF..", // UUID/KSUID
"type": "balance. updated",
"data": { "currency":"EUR", "delta"--5. 00, "balance":125. 37 },
"trace_id": "4e3f.., "//for correlation
"signature": "base64 (hmac (...)) "//optional for partners
}
'type' - домендік таксономия (оқиғалар сөздігін қараңыз).
PII/PCI - шлюз деңгейінде алып тастау/бүркемелеу.
7) Backpressure, квоталар және «қымбат» клиенттерден қорғау
Server → Client: per-connection send-queue «жылжымалы терезесі» бар. Толып кеткен - '1013 '/' policy _ violation' коды бар «шулы» топиктерге немесе disconnect жазылымдарын ысыру.
Client → Server: 'subscribe/unsubscribe' лимиттері (мысалы, ≤ 10/сек), топиктер тізімін шектеу (≤ 50), қайталап жазылудың ең аз аралығы.
Rate limits IP/tenant/кілті бойынша. Аномалиялар → уақытша бұғаттау.
Priority: өмірлік маңызды оқиғалар (баланс, RG-лимиттер) - басым кезек.
8) Қорғау және қауіпсіздік
Хендшейк-эндпоинттегі WAF/бот профилі, рұқсат етілген Origin тізімі.
edge-шлюз пен стрим-тораптар арасындағы mTLS.
DoS-қорғау: L4-те SYN-cookies, ашық WS санына лимиттер/keep-alive аралығы.
Anti-replay: 'timestamp' пайдалы жүктеменің опциондық қолтаңбасында (серіктестер үшін) рұқсат етілген терезе 5 мин.
Жалға алушыларды оқшаулау: физикалық/логикалық шардирлеу, кілттер/per-tenant токендері.
9) Көлік сәулеті
Шлюз (edge): TLS, authN/Z терминейі, квоталар, партияға бағыттау.
Stream-тораптар: 'hash (user_id)% N' бойынша sticky-роутингі бар stateless воркерлер.
Оқиға брокері: Kafka/NATS/Redis Streams - ақиқат көзі және реплика-буфер.
State-сервис: снапшоттарды сақтайды (balance, турнирдегі позициялар).
Мультирегион: актив-актив; GSLB ең жақын аймақ бойынша; home-region логин кезінде бекітіледі; фейловер кезінде - басқа өңірден келген «салқын» резюм.
10) Тәртіп, келісімділік, теңсіздік
Ретке келтiру партияның iшiнде (user/room) ғаламдық емес кепiлдiк берiледi.
Консистенттілік: оқиға REST жауабынан бұрын келуі мүмкін; UX аралық жай-күймен (optimistic UI + reconciliation) өмір сүре білуі тиіс.
Сәйкестік: 'event _ id' қайта өңдеу клиенттің күйін өзгертпейді.
11) Қателер, reconnect және «дауыл»
Жабу кодтары: '1000' (қалыпты), '1008' (policy), '1011' (internal), '1013' (server overload).
Клиенттік экспоненциалдық backoff + jitter: 1s, 2s, 4s... макс 30s.
Жаппай реконнектілер кезінде («thundering herd») - сервер 'retry _ after' және «сұр» жауаптар береді, кеңесімен бірге read-only үшін SSE fallback пайдаланыңыз.
12) Кэш және снапшоттар
Әрбiр жазылу өзектi жай-күйiнiң снапшотынан басталуы мүмкiн, одан кейiн - дифф-оқиғалар ағыны.
'data _ version' схемасын нұсқалау және сыйысымдылық (өрістерді кеңейту клиенттерді бұзбайды).
13) Бақылау және SLO
Өлшемдері:- Қосылыстар: белсенді, белгіленген/сек, жалға алушылар/өңірлер бойынша бөлу.
- Жеткізу: p50/p95 брокерден клиентке дейін кідіріс, drop-rate, resend-rate.
- Сенімділік: снапшотсыз табысты түйіндердің үлесі, gap-детектор.
- Қателер: 4xx/5xx хэндшейкте, жабу кодтары, лимит-хит.
- Жүктеме: RPS 'subscribe' командасы, кезек өлшемі, CPU/NET.
- WS p95 ≤ 500 мс орнату (өңір ішінде).
- End-to-end latency оқиғасы p95 ≤ 300 мс (user-partition).
- Resume success ≥ 99%, message loss = 0 (по at-least-once).
- Uptime стрим-эндпоинт ≥ 99. 95%.
14) Схемалар мен нұсқаларды басқару
Иелері, мысалдары және семантикасы бар оқиғалар сөздігі.
«Жұмсақ» эволюция: тек опциондық өрістерді қосу; жою - '@deprecated' кезеңінен кейін.
Клиенттік SDK-ға қарсы келісімшарттық тесттер, JSON Schema/Protobuf линтерлері.
15) Оқиғалар ойнатқыштары (ортақ ойнатқышқа ендіру)
Latency өсуі: партияларды резервтік түйіндерге ауыстыру, брокердің batch мөлшерін ұлғайту, өмірлік маңызды оқиғаларды басымдыққа қосу.
Реконнектілер дауылы: 'retry _ after' дегенді белсендіру, handshake лимиттерін уақытша көтеру, SSE-фоллбекті қосу.
Токендердің жылыстауы: JWKS ротациясы, қозғалған токендерді қайтарып алу, re-auth-пен мәжбүрлі reconnect.
Брокердің партиясын жоғалту: қалпына келтірілгеннен кейін снапшот, реплика режиміне ауыстыру.
16) API шағын ерекшелігі (жеңілдетілген)
Handshake (HTTP GET → WS):
GET /ws? tenant=acme&client=web
Headers:
Authorization: Bearer <JWT>
X-Trace-Id: <uuid>
Клиенттің командасы:
json
{ "op":"subscribe", "topics":["user:123"], "resume_from":"1748852201:42" }
{ "op":"unsubscribe", "topics":["user:123"] }
{ "op":"ping", "ts":"2025-11-03T12:34:56Z" }
Серверлік жауаптар:
json
{ "op":"ack", "id":"subscribe:user:123" }
{ "op":"event", "topic":"user:123", "seq":"1748852201:43", "type":"balance. updated", "data":{...} }
{ "op":"snapshot", "topic":"user:123", "seq":"1748852201:42", "state":{...} }
{ "op":"error", "code":"acl_denied", "reason":"no access to topic tournament:456" }
{ "op":"pong", "ts":"..." }
17) UAT чек-парағы
- Клиенттің 1/10/60 минуттан кейін оффсеттен резюме.
- Дедуп: сол 'event _ id' қайта жеткізу күйін өзгертпейді.
- Gap-детектор → автоматты 'snapshot' және тегістеу.
- Квоталар және backpressure: жүктелген клиент policy-disconnect алады.
- Мультирегион: оффсетті сақтаумен аймақтың failover.
- Security: JWT аяқталған токен-рокер, ACL-ден тыс жазылу әрекеті.
- RG/оқиғаның балансы REST-тен бұрын/кейін келеді - UI дұрыс «тігеді».
18) Жиі қателер
Жоқ 'seq/offset' және жаңарту - оқиғалар мен сенімділікті жоғалтамыз.
WS мутацияларында күрделі төлем командаларын араластыру - REST пайдаланыңыз.
backpressure/квоталардың болмауы - «ілінген» қосылыстар және жадының көшкіні.
Жаһандық тәртіп - қымбат және қажет емес; партияда тәртіп жеткілікті.
Оқиғаларда PII логині - құпиялылықтың бұзылуы және PCI/GDPR.
Оқиғалар сөздігінің және нұсқаның болмауы - клиенттер бұзылады.
Түйіндеме
WebSocket-стримдері егер олар қорытынды, қорғалған және шектеулі арна ретінде құрылса, реактивті UX және жедел сигналдар береді: WSS + mTLS/JWT, ACL топиктер, seq/offset + resume, ат-least-once дедуппен, backpressure/квоталар, ақиқат көзі ретінде брокер, бақылау және SLO. Осылайша, ағындар пайдаланушы үшін жылдам және платформа үшін басқарылатын болып қалады - қауіпсіздік пен ақша бойынша ымырасыз.