gRPC vs REST в iGaming
1) Контекст iGaming: навіщо взагалі вибирати протокол
iGaming-платформа одночасно обслуговує:- Реальний час: фіди коефіцієнтів, лайв-ставки, стрімінг статусів купона/матчу, ліміти гравця, миттєві блокування;
- транзакції: депозит/виведення, розрахунок ставок, бонуси, KYC/AML, тікети на підтримку;
- партнерські/В2В інтеграції: провайдери ігор, платіжні шлюзи, афіліати, регулятори.
Від протоколу залежать p99-латентність, стабільність під піками (матчі, фінали), зручність інтеграцій і вартість експлуатації.
2) Коротко: що таке REST і gRPC
REST/HTTP/JSON: людиночитаний, універсальний. Відмінно працює з браузерами/мобільними SDK, кешується CDN, легко дебажити.
gRPC (HTTP/2 + Protobuf): бінарні контракти, автогенерація клієнтів, uni/bi-directional стрімінг, мультиплексування, строгі схеми. Сервіс-к-сервіс по мережі - його стихія.
3) Де що доречно в iGaming
gRPC - сильні сторони
Лайв-фіди та трекінг: стрім коефіцієнтів, подій матчу, лімітів (server streaming/bidi).
Внутрішні мікросервіси: ризик-рушій, котирувальник, скоринг антифроду, баланс/гаманець - вимоги до p99/CPU.
Великий оборот RPS з короткими повідомленнями (низька ціна на байт, малий GC-pressure).
Суворі контракти між командами і версіями (Protobuf з backward-compat).
REST - сильні сторони
Публічні та партнерські API: проста інтеграція (curl/Postman), партнери без gRPC-стека.
Браузерний фронт: нативно, без проксі; підтримка кешу/ETag/304/CDN.
Довгоживучі ресурси: каталоги ігор, профілі, звіти, конфігурації.
Регуляторні вивантаження: JSON/CSV-сумісність без шлюзів.
4) Латентність і пропускна здатність
gRPC економніший за розміром корисного навантаження (Protobuf) і витратами на серіалізацію/десеріалізацію, виграє на коротких і частих викликах.
REST/JSON додає 30-200% до корисного навантаження, але виграє за рахунок кешування і CDN на публічних GET.
Рекомендація: всередині DC/міжсервісно - gRPC за замовчуванням; назовні - REST, крім реального часу.
5) Реальний час: лайв-ставки і котирування
Параметри:- gRPC server streaming / bidi: постійний потік для оновлень, backpressure, контроль вікна.
- gRPC-Web (через Envoy) для браузера, якщо потрібен бінарний протокол на фронті.
- WebSocket/SSE + REST: коли екосистема gRPC-Web не підходить або потрібен чистий браузер без проксі.
Патерн: всередині - gRPC стріми від котирувача до API-шлюзу/edge; назовні - WebSocket/SSE для фронту, REST для CRUD.
6) Ідемпотентність, порядок і гарантії доставки
REST: 'Idempotency-Key'для POST на шлюзі, повторна подача при таймауті; ключ - в Redis/БД c TTL.
gRPC: ретраї на рівні клієнта/балансувальника + ідемпотентні методи ('retriable _ status _ codes') і sequence/версіонування в повідомленнях стрімінгу.
Для розрахунку ставок використовуйте Inbox/Outbox + UPSERT на синці (див. статті про дедуплікацію та порядок) - протокол сам по собі гарантій бізнес-ефекту не дає.
7) Безпека та комплаєнс
Транспорт: TLS/mTLS і в mesh, і на edge; в gRPC простіше скрізь тримати mTLS (SPIFFE/SPIRE).
Автентифікація: обидва варіанти підтримують OAuth2/OIDC (JWT в'Authorization: Bearer'), для gRPC - метадані.
Підписи/НМАС: частіше в REST-інтеграціях B2B.
PII/логування: бінарні payload gRPC складніше випадково «пролити» в логи, але використовуйте маскування в будь-якому випадку.
Регулятори часто вимагають людські вивантаження - REST/JSON зручніше.
8) Спостережуваність і експлуатація
Обидва формати чудово працюють з OpenTelemetry: 'traceparent'( REST )/gRPC-інтерсептори.
gRPC дає багаті статуси/трейлери; REST - звичні коди HTTP і прошарки CDN/WAF.
На шлюзі: rate limiting/quota, circuit breaker, outlier detection, fault injection - однаково доступні (Envoy/Kong/NGINX/Traefik).
9) Сумісність і фронт
Чистий браузер не говорить gRPC з коробки → gRPC-Web або REST/WS/SSE.
Мобільні клієнти (iOS/Android) - gRPC-клієнти доступні, але розмір SDK і політика стору іноді підштовхують до REST.
10) Архітектурні патерни змішаного периметра
10. 1 Стратегія «подвійний фасад»
Всередині (east-west): gRPC.
Назовні (north-south): REST + WS/SSE.
Транскодинг на edge (Envoy): один бекенд, два клієнти.
yaml
Envoy: REST ↔ gRPC transcoding (фрагмент)
typed_per_filter_config:
envoy.filters.http.grpc_json_transcoder:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder proto_descriptor: "descriptors.pb"
services: ["betting.BetsService"]
print_options:
preserve_proto_field_names: true
10. 2 gRPC-Web
Браузер → Envoy (gRPC-Web) → gRPC-сервіс. Зручно для live-віджетів і адмінських UI.
11) Контракти та еволюція API
Protobuf (gRPC)
Тільки розширюйте повідомлення (додавайте поля з новими тегами), не змінюйте семантику і типи.
proto syntax = "proto3";
package betting;
service BetsService {
rpc PlaceBet(PlaceBetRequest) returns (PlaceBetResponse);
rpc LiveOdds(EventsFilter) returns (stream OddsUpdate); // серверный стрим
}
message PlaceBetRequest {
string account_id = 1;
string event_id = 2;
double stake = 3;
string selection = 4;
string idempotency_key = 5;
}
OpenAPI (REST)
Версіонування по шляху '/v1', нові поля тільки опціональні.
yaml openapi: 3.0.3 info: { title: Bets API, version: "1.0" }
paths:
/v1/bets:
post:
operationId: placeBet parameters:
- in: header name: Idempotency-Key required: true schema: { type: string }
requestBody:
required: true content:
application/json:
schema:
$ref: '#/components/schemas/PlaceBetRequest'
responses:
'201': { description: Created }
components:
schemas:
PlaceBetRequest:
type: object required: [accountId, eventId, stake, selection]
properties:
accountId: { type: string }
eventId: { type: string }
stake: { type: number, format: double }
selection: { type: string }
12) Кейси iGaming: що вибрати
13) Виробничі нюанси
Таймаути/ретраї
gRPC: 'per _ try _ timeout', обмежити'max _ attempts', ретраї тільки для ідемпотентних RPC.
REST: експоненціальний backoff, джиттер, 429/5xx-політики на шлюзі.
Обмеження тіла/методу
REST: ліміти на розмір запиту,'Content-Type'валідація.
gRPC: ліміти на розмір повідомлень, flow control.
Кешування
REST: `Cache-Control`, `ETag`.
gRPC: кеш на рівні додатку/шлюзу (для unary), для стрімів - снапшоти/зрізи.
Спостережуваність
Обов'язкові: лог кореляції (request id), спани, метрики помилок за маршрутом/методом, розподіл p50/p95/p99.
14) Анти-патерни
«Переписати все на gRPC» і намагатися віддавати фронту безпосередньо - без gRPC-Web/проксі це зламає браузер.
Публічні веб-ендпоінти тільки gRPC-ом - партнери відваляться.
Стримити лайв-фіди через REST-полінг - перевантаження мережі/бекенду і повільні котирування.
Ретраїти неідемпотентні операції (створення ставки/платіж) на рівні клієнта.
Покладатися на фізичний час для порядку подій замість версій/sequence.
15) Чек-лист вибору протоколу
- Трафік realtime або CRUD/партнерський?
- Клієнти - браузер/партнери або мікросервіси/мобільні SDK?
- Потрібен стримінг (server/bidi)?
- Потрібні CDN/кеші на периметрі?
- Які SLO по p99 і бюджет помилок?
- Чи є вимоги регулятора до форматів звітності (JSON/CSV)?
- План ідемпотентності і дедупа визначено?
- Інтеграція з API-шлюзом/mesh готова (mTLS, ліміти, трансляція)?
- Стратегія версіонування та сумісності затверджена?
- Дашборди/алерти і тест-плейбуки на піки «матч-дня» готові?
16) Міні-плейбуки (Game Days)
Матч-пік: подвоїти RPS лайв-фідів → оцінити p99 і втрати повідомлень (стріми).
Провал провайдера: падіння апстріму - CB/outlier повинні відсіяти, фронт - деградувати до останнього снапшоту.
Регрес шлюзу: відключити трансляцію gRPC↔REST - переконатися, що fallback (WS/SSE) працює.
Мережеві затримки/WAN: штучно підняти RTT → перевірити адаптацію таймаутів і backoff.
Великі тіла (KYC): перевірити ліміти/багаторазові завантаження, резюмування.
17) Підсумки
Всередині кластера: gRPC - дефолт для продуктивності, суворих контрактів і стрімінгу.
На периметрі: REST (і WS/SSE для real-time UI) - дефолт для широкої сумісності.
Зшиваємо світи через API-шлюз (транскодинг, ліміти, аутентифікація) і service mesh (mTLS, політика трафіку).
Успіх - у змішаній архітектурі з чітким розмежуванням: стримінг/низька латентність всередині, зручність і універсальність зовні.