GH GambleHub

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: клієнт шле'ping'кожні 20-30 с, таймаут відповіді 10 с. Сервер скидає з'єднання при 3 таймаутах поспіль.
Компресія: 'permessage-deflate', ліміт на розмір кадру (наприклад, ≤ 64 KB).
Формат корисного навантаження: JSON для зовнішніх, Protobuf/MsgPack для внутрішніх/мобільних.

3) Автентифікація та авторизація

Хендшейк з JWT в query/header ('Sec-WebSocket-Protocol '/' Authorization'), TTL токена короткий (≤ 15 хв), refresh по out-of-band (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'з'reason'.

5) Гарантії доставки та резюмування

Мета: at-least-once на канал + ідемпотентність у клієнта.

Кожна подія має монотонний'seq'в рамках «партії» (зазвичай user/room) і глобальний'event _ id'для дедупа.
При ре-коннекті клієнт передає'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 з «ковзним вікном». Переповнений - скидання підписок на «галасливі» топіки або disconnect з кодом'1013 '/' policy _ violation'.
Client → Server: ліміти на'subscribe/unsubscribe'( наприклад, ≤ 10/сек), обмеження списку топіків (≤ 50), мінімальний інтервал повторної підписки.
Rate limits за IP/tenant/ключем. Аномалії → тимчасове блокування.
Priority: життєво важливі події (баланс, RG-ліміти) - пріоритетна черга.

8) Захист і безпека

WAF/бот-профіль на хендшейк-ендпоінті, список дозволених Origin.
mTLS між edge-шлюзом і стрім-вузлами.
DoS-захист: SYN-cookies на L4, ліміти на число відкритих WS/інтервал keep-alive.
Anti-replay: «timestamp» в опціональному підписі корисного навантаження (для партнерів) з допустимим вікном 5 хв.
Ізоляція орендарів: фізичне/логічне шардування, ключі/токени per-tenant.

9) Транспортна архітектура

Шлюз (edge): термінейт TLS, authN/Z, квоти, маршрутизація на партію.
Stream-вузли: stateless-воркери з sticky-роутингом по'hash (user_id)% N'.
Брокер подій: Kafka/NATS/Redis Streams - джерело істини і реплей-буфер.
State-сервіс: зберігає снапшоти (balance, позиції в турнірі).
Мультирегіон: актив-актив; GSLB по найближчому регіону; home-region закріплюється при логіні; при фейловері - «холодний» резюм з іншого регіону.

10) Порядок, узгодженість, ідемпотентність

Впорядкованість гарантується всередині партії (user/room), не глобально.
Консистентність: подія може прийти раніше REST-відповіді; UX повинен вміти жити з проміжним станом (optimistic UI + reconciliation).
Ідемпотентність: повторна обробка'event _ id'не змінює стан клієнта.

11) Помилки, reconnect і «шторму»

Коди закриття: `1000` (normal), `1008` (policy), `1011` (internal), `1013` (server overload).
Клієнтський експоненціальний backoff + jitter: 1s, 2s, 4s… макс 30s.
Під час масових реконнектів («thundering herd») - сервер віддає'retry _ after'і «сірі» відповіді з підказкою використовувати SSE fallback для read-only.

12) Кеш і снапшоти

Кожна підписка може починатися зі снапшота актуального стану, потім - потік диф-подій.
Версіонування схеми'data _ version'і сумісність (розширення полів не ламає клієнтів).

13) Спостережуваність і SLO

Метрики:
  • З'єднання: активні, встановлені/сек, розподіл по орендарях/регіонах.
  • Доставка: p50/p95 затримки від брокера до клієнта, drop-rate, resend-rate.
  • Надійність: частка успішних резюмів без снапшоту, gap-детектор.
  • Помилки: 4xx/5xx на хендшейку, коди закриття, ліміт-хіти.
  • Навантаження: RPS команд'subscribe', розмір черг, CPU/NET.
SLO орієнтири:
  • Встановлення 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, відгук порушених токенів, примусовий reconnect з re-auth.
Втрата партії брокера: переведення в режим снапшотів, реплей після відновлення.

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, at-least-once з дедупом, backpressure/квоти, брокер як джерело істини, спостережуваність і SLO. Так стріми залишаються швидкими для користувача і керованими для платформи - без компромісів з безпеки і грошей.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.