Webhooks және оқиғаның ұқсастығы
TL; DR
Жақсы вебхук - бұл қол қойылған (HMAC/mTLS), қорытынды және іспеттес оқиға, экспоненциалды backoff және алушыда дедупликациясы бар at-least-once моделі бойынша жеткізіледі. Конверт ('event _ id', 'type', 'ts', 'version', 'attempt', 'signature'), уақыт терезесі (≤ 5 мин), жауап кодтары, ретрайлер, DLQ және статус-эндпоинт туралы келісіңіз.
1) Жеткізу рөлдері мен моделі
Жіберуші (сіз/провайдер): оқиғаны қалыптастырады, қол қояды, 2xx дейін жеткізуге тырысады, 3xx/4xx/5xx кезінде ретраит (анық «қабылдамаңыз»), DLQ жүргізеді, replay API береді.
Алушы (серіктесіңіз/қызметіңіз): қолтаңбаны/уақытша терезені тексереді, дедуп және идемпотенттік өңдеуді жасайды, дұрыс кодпен жауап береді ,/status және/ack replay 'event _ id' бойынша ұсынады.
Кепілдіктер: at-least-once. Алушы телнұсқаларды өңдей және тәртіпті өзгерте білуі тиіс.
2) Оқиға конверті (envelope)
json
{
"event_id": "01HF7H9J9Q3E7DYT5Y6K3ZFD6M",
"type": "payout.processed",
"version": "2025-01-01",
"ts": "2025-11-03T12:34:56.789Z",
"attempt": 1,
"producer": "payments",
"tenant": "acme",
"data": {
"payout_id": "p_123",
"status": "processed",
"amount_minor": 10000,
"currency": "EUR"
}
}
Міндетті өрістер: 'event _ id', 'type', 'version', 'ts', 'attempt'.
Эволюция ережелері: өрістерді қосамыз; түрлерді жою/ауыстыру - тек жаңа 'version'.
3) Қауіпсіздік: қолтаңбалар және байланыстыру
3. 1 HMAC қолтаңбасы (әдепкі бойынша ұсынылады)
Тақырыптар:
X-Signature: v1=base64(hmac_sha256(<secret>, <canonical>))
X-Timestamp: 2025-11-03T12:34:56Z
X-Event-Id: 01HF7...
Канондық жол:
<timestamp>\n<method>\n<path>\n<sha256(body)>
Алушыда тексеру:
- abs(now − `X-Timestamp`) ≤ 300s
- 'X-Event-Id' бұрын өңделмеген (дедуп)
- 'X-Signature' сәйкес келеді (тайм-қауіпсіз салыстырумен)
3. 2 Қосымша. шаралар
mTLS сезімтал вебхуктер үшін.
IP/ASN allow-list.
DPoP (қосымша) sender-constrained үшін, егер вебхук кері қоңырауларды бастаса.
4) Ұқсастық және дедупликация
4. 1 Оқиғаның ұқсастығы
Бірдей 'event _ id' оқиғасы күйін қайта өзгертпеуі керек. Алушы:- TTL ≥ 24-72 сағ., демпотенттік кеште (KV/Redis/ДБ) 'event _ id' сақтайды;
- қайта беру үшін өңдеу нәтижесін (табысты/қате, артефактілер) сақтайды.
4. 2 Командалардың теңсіздігі (кері шақырулар)
Егер вебхук клиентті API-ні тартуға мәжбүрлесе (мысалы, «payout растай»), 'Idempotency-Key' дегенді сол REST-қоңырауда пайдаланыңыз, нәтижені сервис жағында сақтаңыз (exactly-once outcome).
KV моделі (ең аз):
key: idempotency:event:01HF7...
val: { status: "ok", processed_at: "...", handler_version: "..." }
TTL: 3d
5) Ретраи және backoff
Ұсынылатын кесте (джиттермен экспоненциалды):- '5s, 15s, 30s, 1m, 2m, 5m, 10m, 30m, 1h, 3h, 6h, 12h, 24h' (бұдан әрі күн сайын N күнге дейін)
- 2xx - сәттілік, ретрацияны тоқтату.
- '400/ 401/403/404/422' - егер қолтаңба/ok пішімі (клиенттік қате) болса, ретраим емес.
- '429' - 'Retry-After' немесе backoff ретраимі.
- 5хх/желілік - ретраим.
Жіберушінің атауы: 'User-Agent', 'X-Webhook-Producer', 'X-Attempt'.
6) Алушы жағында өңдеу
Псевдопайплайн:pseudo verify_signature()
if abs(now - X-Timestamp) > 300s: return 401
if seen(event_id):
return 200 // идемпотентный ответ
begin transaction if seen(event_id): commit; return 200 handle(data) // доменная логика mark_seen(event_id) // запись в KV/DB commit return 200
Транзакциялану: «seen» белгісі істен шыққан кезде екі рет өңдеуді болдырмау үшін операция әсерімен (немесе нәтиже тіркелгеннен кейін) атомарлы түрде қойылуы тиіс.
7) Тәртіп пен снапшот кепілдіктері
Тәртіп кепілдендірілмейді. Өзектілігін салыстыру үшін 'ts' және 'seq '/' version' домендерін 'data' пайдаланыңыз.
Ұзақ лагтар/шығындар үшін - жіберушіден/replay және алушыдан/resync қосыңыз (уақыт/ID терезесі бойынша снапшот және дельта алу).
8) Мәртебесі, replay және DLQ
8. 1 Жіберушінің эндпоинттары
'POST/webhooks/replay' - 'event _ id' тізімі немесе уақыт терезесі бойынша.
'GET/webhooks/events/: id' - бастапқы буманы және әрекеттер тарихын көрсету.
DLQ: «өлі» оқиғалар (ретрайлардың лимиті таусылды) → жеке сақтау орны, алерталар.
8. 2 Алушының эндпоинттары
`GET /webhooks/status/:event_id` — `seen=true/false`, `processed_at`, `handler_version`.
'POST/webhooks/ack' - DLQ бағдарламасынан қолмен өңдеуді растау.
9) Қателер келісімшарттары (алушының жауабы)
http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
Retry-After: 120
X-Trace-Id: 4e3f...
{
"error": "invalid_state",
"error_description": "payout not found",
"trace_id": "4e3f..."
}
Ұсыныстар: әрқашан нақты кодты қайтарыңыз және егер мүмкін болса, 'Retry-After'. Қауіпсіздіктің егжей-тегжейін қайтармаңыз.
10) Мониторинг және SLO
Өлшемдері (жіберуші):- delivery p50/p95, success rate, ретр/оқиға, drop-rate DLQ, share 2xx/4xx/5xx, 2xx дейін кідіріс терезесі.
- verify fail rate (қолы/уақыты), dup-rate, latency handler p95, 5xx.
- Жеткізу: 99 ≥. Оқиғалардың 9% 2xx <3 c p95 алады (бірінші сәтті әрекеттен кейін).
- Криптографиялық тексеру: қолды валидациялау ≤ 2-5 мс p95.
- Дедуп: 0 қайталама эффекттер (домен деңгейінде exactly-once outcome).
11) Деректер қауіпсіздігі және құпиялылық
Вебхук теледидарында PAN/PII таратпаңыз; Авторизацияланған API бойынша егжей-тегжейлі идентификаторларды және келесі pull пайдаланыңыз.
Өрістердегі сезімтал өрістерді жасырыңыз; TTL-мен оқиғаларды барынша аз сақтаңыз.
DLQ қоймасы мен реплиін шифрлаңыз.
12) Нұсқалау және үйлесімділік
'version' нұсқасы (конверт) және '/webhooks/v1/payments 'жолында.
Жаңа өрістер - опциондық; жою - «Sunset» кезеңінен кейін ғана.
machine-readable changelog бағдарламасындағы өзгерістерді құжаттаңыз.
13) Тест-кейстер (UAT чек-парағы)
- Сол 'event _ id' → бір әсерді және '200' дубликаттарды қайта жеткізу.
- Қолы: дұрыс кілт, дұрыс емес кілт, ескі кілт (ротация), терезеден тыс 'X-Timestamp'.
- Backoff: алушы '429' s 'Retry-After' → дұрыс үзіліс береді.
- Тәртібі: '... processed' оқиғалары '... created' → дұрыс өңдеу/күту алдында келеді.
- 'mark _ seen' → атомарлық/қайталау әсері арасындағы ДБ алушыда жаңылысы.
- DLQ және қолмен replay → сәтті жеткізу.
- Жаппай «дауыл» (провайдер қораптарды жібереді) → шығынсыз, лимиттер өте қиын тұншықтырмайды.
14) Шағын сниппеттер
Жіберушінің қолы (жалған):pseudo body = json(event)
canonical = ts + "\n" + "POST" + "\n" + path + "\n" + sha256(body)
sig = base64(hmac_sha256(secret, canonical))
headers = {"X-Timestamp": ts, "X-Event-Id": event.event_id, "X-Signature": "v1="+sig}
POST(url, body, headers)
Алушыны тексеру және атау (жалған):
pseudo assert abs(now - X-Timestamp) <= 300 assert timingSafeEqual(hmac(secret, canonical), sig)
if kv.exists("idemp:"+event_id): return 200
begin tx if kv.exists("idemp:"+event_id): commit; return 200 handle(event.data) // доменная логика kv.set("idemp:"+event_id, "ok", ttl=259200)
commit return 200
15) Жиі қателер
Дедуп жоқ → қайталама әсерлер (қос рефандар/пэйауттар).
Таймштампсыз/терезесіз қолтаңба → replay.
Барлық әріптестерге бір HMAC-құпияны сақтау.
Нәтижені белгілегенге дейін '200' жауаптары → crash кезінде оқиғаларды жоғалту.
Қауіпсіздік бөлшектерін жауаптарға/логтарға «жуу».
DLQ/репликаның болмауы - тосын оқиғалар шешілмейді.
16) Енгізу шпаргалкасы
Қауіпсіздік: HMAC v1 + 'X-Timestamp' + 'X-Event-Id', терезе ≤ 5 мин; mTLS/IP allow-list қажет болғанда.
Конверт: `event_id`, `type`, `version`, `ts`, `attempt`, `data`.
Жеткізу: at-least-once, backoff джиттермен, 'Retry-After', DLQ + replay API.
Теңсіздік: KV-кеш 24-72 сағ, + 'mark _ seen' әсерін атомарлық бекіту.
Бақылануы: жеткізу өлшемдері, қолдар, телнұсқалар; 'trace _ id' трассировкасы.
Құжаттама: нұсқа, жауап кодтары, мысалдар, UAT-чек парағы.
Түйіндеме
Берік вебхактар үш китке салынады: қол қойылған конверт, at-least-once жеткізу және идемпотенттік өңдеу. Келісімшартты рәсімдеңіз, HMAC/mTLS және уақыт терезесін қосыңыз, + DLQ ретраларын және репликаларын іске асырыңыз, іспеттес белгілерді сақтаңыз және атомарлық әсерлерді белгілеңіз. Сонда оқиғалар желі істен шыққанда, жүктеме шыңында және сирек «тағдырдың көшірмелері» кезінде де сенімді болып қалады.