Реалтайм-фид событий: архитектура и безопасность
Real-time фид событий — это «кровеносная система» продуктов с геймификацией, антифродом, CRM-триггерами и выплатами. Чтобы он работал предсказуемо при пиках, не дублировал награды и не протекал данными, нужна строгая архитектура: от протоколов и шины до подписи, идемпотентности, бюджет-каперов и наблюдаемости.
1) Цели и требования
Надёжность: поставка событий с минимальным лагом (p95 ≤ 250 мс ingest, p95 ≤ 1–2 с до потребителя).
Доставка: at-least-once транспорт + логическая exactly-once через идемпотентность.
Порядок: упорядочивание по ключу (обычно `user_id`) с окнами переупорядочивания.
Безопасность: MTLS, HMAC/JWT, ротация ключей, защита от replay/дубликатов, минимизация PII.
Масштаб: горизонтальный шардинг, backpressure, rate limiting, DLQ/реплей.
Управляемость: schema registry, версионирование, миграции без простоя.
Комплаенс: аудит (WORM), RG/KYC гейты, geo-политики, GDPR/анонимизация.
2) Опорная архитектура (слой за слоем)
1. Producers (источники): игровой сервер, кошелёк/платёжка, KYC/AML, клиентские SDK (web/iOS/Android).
2. API Gateway (Ingress): приём HTTP/gRPC, валидация схемы, аутентификация, HMAC/MTLS, нормализация времени.
3. Queue/Stream: Kafka/Rabbit/Cloud Pub/Sub — буферизация, партиционирование по `user_id`.
4. Stream Processor: нормализатор, обогащение, маршрутизация тем, анормалия/антибот флаги, идемпотентная запись.
5. Consumers: Rules/Scoring, Reward Orchestrator, CRM/CDP коннекторы, антифрод, аналитические sink’и.
6. Storage: сырые события (immutable), витрины, индекс для идемпотентности, аудит-журнал.
7. Observability: метрики, логи, трассировки, алерты; panics → DLQ.
8. Admin Plane: schema registry, ключи/секреты, RBAC/ABAC, фичефлаги, реплей-сервис.
3) Протоколы доставки: когда что использовать
HTTP/JSON (server-to-server вебхуки): просто, совместимо, хорош для внешних партнёров. Добавить HMAC + идемпотентность.
gRPC/Protobuf: низкая задержка, строгие схемы, bidi-стримы для внутренних сервисов.
WebSocket/SSE: push в клиент, UI-подписки на лидерборды и прогресс.
CDC/Kafka Connect: когда источники — БД/кошельки, а не бизнес-сервисы.
Рекомендация: внешний периметр — HTTP+HMAC+MTLS; внутри — gRPC/Protobuf.
4) Модель события и конвенции
json
{
"event_id": "e_01HF3Z8Z7Q8Q2K", "event_type": "bet", "schema_version": "1.3.0", "occurred_at": "2025-10-24T11:37:21Z", "ingested_at": "2025-10-24T11:37:21.183Z", "key": { "user_id": "u_12345" }, "ctx": {
"session_id": "s_778", "platform": "ios", "geo": "TR", "device_fp": "fp_4a1..."
}, "payload": {
"game_id": "slot_wolf", "bet": 0.5, "win": 1.25, "currency": "EUR", "provider": "GameCo"
}, "sig": {
"algo": "HMAC-SHA256", "kid": "k_2025_10", "ts": 1730061441, "mac": "c7b7b3...f1"
}
}
Правила:
- Два времени: `occurred_at` (источник) и `ingested_at` (шлюз). Допускайте дрейф часов ±300 с.
- Ключ маршрутизации — то, что определяет порядок (обычно `user_id`).
- PII только в `ctx`/`payload` по принципу минимизации; для чувствительных атрибутов — токенизация.
5) Доставка, порядок и идемпотентность
At-least-once транспорт → возможны дубликаты и переупорядочивание.
Exactly-once логика: держите таблицу идемпотентности c уникальным индексом по `(event_id)` и/или `(user_id, source_seq)`; повтор — no-op.
SQL-скетч:sql
CREATE TABLE event_log (
event_id TEXT PRIMARY KEY, user_id TEXT, event_type TEXT, occurred_at TIMESTAMPTZ, payload JSONB
);
-- вставка с защитой от дублей
INSERT INTO event_log(event_id, user_id, event_type, occurred_at, payload)
VALUES (:event_id,:user_id,:event_type,:occurred_at,:payload)
ON CONFLICT (event_id) DO NOTHING;
Порядок: партиционирование потока по `user_id` + reordering window 60–120 с в процессоре. Позже пришедшие события попадают в «переигровку» (replay) корректирующих функций.
6) Backpressure и управление пиками
Token-bucket rate limiting на ingress (per-IP, per-partner, per-key).
Circuit breaker: при 5xx от внутренних потребителей → деградация (дропаут необязательных событий, очереди увеличивают ретрай-интервалы).
DLQ: перманентно ошибочные сообщения (битая схема, подпись невалидна, превышен TTL подписи).
Replay сервис: выборочный репаблиш из DLQ по `event_id`/диапазону времени.
7) Схемы и эволюция: как не «сломать» прод
Schema Registry: JSON Schema/Protobuf; политики совместимости: backward для продюсеров, forward для консьюмеров.
Версионирование: `schema_version`, мажорные — только через фичефлаг и двойную запись (dual-write).
Контракты: продвижение схемы после канареечного периода и green metrics.
YAML-пример правила проверки:yaml compatibility:
enforce: true mode: backward blocked_fields:
- payload.ssn
- payload.card_number required_fields:
- event_id
- event_type
- occurred_at
8) Модель угроз и защита
Угрозы: подмена тела, повтор (replay), утечка PII, компрометация ключа, schema-poisoning, DoS, MITM, сигнатура-stripping.
Защита:- MTLS на периметре: клиентские сертификаты с коротким сроком, CRL/OCSP.
- HMAC-подпись тела + `X-Timestamp` и TTL (±300 с).
- JWT (client credentials/OAuth2) — для авторизации и ограничений по scope.
- Ротация ключей (KMS): `kid` в заголовке; план ротации 30–90 дней; двойная проверка в окне миграции.
- Nonce/идемпотентность: `X-Request-Id` для запросов-побочек (выплаты, бонусы); храните на время TTL.
- Content-Type pinning, max body size, allow-list IP/ASN для критичных интеграций.
- WORM-аудит всех входящих raw-payload + заголовков (неизменяемое хранилище).
python body = request.raw_body ts = int(request.headers["X-Timestamp"])
assert abs(now() - ts) <= 300 # анти-replay kid = request.headers["X-Key-Id"]
secret = kms.fetch(kid)
mac = hmac_sha256(secret, body)
assert hmac_eq(mac, request.headers["X-Signature"])
9) Приватность, PII и RG/KYC
Минимизация: PII передавать по ссылке-токену (на 5–15 минут) вместо инлайна; редактирование/анонимизация в сырых логах запрещены — используйте отдельные PII-сторанцы.
Доступ: ABAC по атрибутам юрисдикции и роли; все чтения — в аудит-журнал.
GDPR: право на удаление реализуйте через key-mapping, чтобы стереть PII без ломки фактов событий.
RG/KYC: события, требующие выдачи ценных наград, пропускайте только при валидном KYC-уровне и RG-флагах «OK».
10) Наблюдаемость и SLO
SLO (пример):- Ingest p95 ≤ 250 мс; end-to-end p95 ≤ 2 с; отказ ≤ 0.1%/сутки.
- Подпись-ошибки (HMAC/JWT) ≤ 0.02% от общего потока.
- DLQ fill rate ≤ 0.1%; «дубликаты» после идемпотентности ≤ 0.005%.
- RPS по источникам, p50/p95 latency, 4xx/5xx, подписи-ошибки, time-skew.
- Lag по партициям, переработка/сек, fill DLQ, retries, реплей-объёмы.
- Схемы: доля сообщений по версиям, нарушения совместимости.
- Безопасность: частота rps-throttle, circuit-breakers, аномалии IP/ASN.
- SRM потока (резкий перекос трафика из одного источника).
- Латентность p95 > целевого 5 мин+, рост DLQ > X/min.
- Подписи-ошибки > Y ppm, всплеск повторов `X-Request-Id`.
- Drift часов > 120 с у источника.
11) Мульти-регион и отказоустойчивость
Active-Active регионы, глобальный роутинг (GeoDNS/Anycast), sticky-key по `user_id` → регион.
Кросс-региональный репликационный топик для критичных событий (денежные, KYC).
Blast radius: изоляция по тенантам/брендам, отдельные бюджеты и ключи.
DR-план: RPO ≤ 5 мин, RTO ≤ 30 мин; регулярные репетиции.
12) Политики ретеншна и реплея
Сырые события: 7–30 дней (по стоимости), агрегаты/витрины — дольше.
Реплей разрешён только по подписанному runbook (кто, что, почему, диапазон времени).
Реплей всегда идёт в новый stream-version с флагом `replayed=true` для аналитической прозрачности.
13) Примеры конфигураций
Ingress (NGINX-стиль) лимиты:nginx limit_req_zone $binary_remote_addr zone=req_limit:10m rate=300r/s;
limit_req zone=req_limit burst=600 nodelay;
client_max_body_size 512k;
proxy_read_timeout 5s;
Kafka (пример):
properties num.partitions=64 min.insync.replicas=2 acks=all retention.ms=604800000 # 7 days compression.type=zstd
Policy для ключей (KMS):
yaml rotation_days: 45 grace_period_days: 7 allow_algos: ["HMAC-SHA256"]
key_scopes:
- topic: "wallet_events"
producers: ["wallet-svc"]
consumers: ["ledger-svc","risk-svc"]
14) Чек-лист запуска real-time фида
- MTLS на периметре, HMAC/JWT, ротация ключей (`kid`).
- Идемпотентность на логике (уникальные ключи, upsert/ON CONFLICT).
- Партиционирование по `user_id`, reordering window, реплей-сервис.
- Schema registry + политики совместимости; dual-write при major-апдейтах.
- Rate limiting, circuit breakers, DLQ + ручной ревью.
- Наблюдаемость: SLO, алерты по подписи/латентности/DLQ/lag.
- Политика PII/анонимизации, ABAC, аудит WORM.
- DR/мульти-регион, репетиции фейловера.
- Runbooks: инциденты, реплей, откат схем/ключей.
15) Мини-кейс (синтетический)
Контекст: пик турниров, 120 к RPS ingress, 64 партиции, 2 региона Active-Active.
Итого за 4 недели: ingest p95 210 мс, e2e p95 1.6 с; DLQ 0.05%; подписи-ошибки 0.009%; дубликаты после идемпотентности 0.003%.
Инцидент: дрейф часов у партнёра (−9 мин) → всплеск anti-replay. Circuit breaker перевёл поток в «буферный» эндпоинт, partner-health оповестил CSM; после синка NTP — реплей окна 12 мин всем консьюмерам. Потерь и двойных выплат нет.
16) Резюме
Надёжный real-time фид — это не «просто вебхуки». Это слоистая система с чёткими контрактами: at-least-once транспорт + логическая exactly-once, схема-регистры и версионирование, MTLS/HMAC/JWT и ротация ключей, backpressure/DLQ/реплей, минимизация PII и строгий аудит. Соблюдая эти практики, вы получите быстрый, безопасный и предсказуемый поток событий, на котором можно уверенно строить геймификацию, антифрод, CRM и выплаты.