Webhooks: gaýtalanmalar we kwitasiýa
1) Eltmegiň esasy modeli
At-least-once (adaty): waka 1 gezek ≥. Kepillikler kabul edijiniň duýgurlygy bilen birmeňzeş gazanylýar.
Kwitasiýa (ACK): Alyjydan diňe islendik 2xx (adatça 200/204) üstünlik gazanmagy aňladýar. Galan zatlaryň hemmesi ret etmek hökmünde düşündirilýär we gaýtalanmaga eltýär.
Çalt ACK: Wakany öz gezeginde ýerleşdirenden soň 2xx jogap beriň.
2) Wakalaryň formaty we hökmany sözbaşylar
Peýdaly ýük (mysal)
json
{
"id": "evt_01HXYZ",
"type": "order. created",
"occurred_at": "2025-11-03T18:10:12Z",
"sequence": 128374,
"source": "orders",
"data": { "order_id": "o_123", "amount": "49. 90", "currency": "EUR" },
"schema_version": 1
}
Iberijiniň sözbaşylary
'X-Webhook-Id: evt_01HXYZ' - wakanyň özboluşly ID-si.
'X-Webhook-Seq: 128374' - monoton yzygiderlilik (abuna/tema boýunça).
`X-Signature: sha256=<base64(hmac_sha256(body, secret))>` — HMAC-подпись.
'X-Retry: 0,1,2...' - synanyşyk belgisi.
'X-Webhook-Version: 1' - şertnamanyň wersiýasy.
(goşmaça) 'Traceparent' - ýollaryň baglanyşygy.
Alyjynyň jogaby
2xx - üstünlikli kabul edildi (bu 'id' boýunça mundan beýläk gaýtalanmalar bolmaz).
410 Gone - endpoint öçürildi/hereketsiz → iberiji gaýtalanmagy bes edýär we abunalygy öçürýär.
429/5xx/wagt - iberiji retraý syýasaty boýunça gaýtalaýar.
3) Gaýtalama syýasaty (retries)
Maslahat berlen backoff (jitter)
'1s, 3s, 10s, 30s, 2m, 10m, 30m, 2h, 6h, 24h' (48-72 sagat ýaly çäkden soň durýarys).
Düzgünler:- "Süri täsirinden" gaça durmak üçin eksponensial backoff + tötänleýin jitter (20-30% ±).
- Wagtlaýyn şowsuzlyklar üçin ýalňyşlyklaryň kworumy (mysal üçin, 5xx ýa-da toruň wagty).
- Respect 429: minimum 'min' goýuň (Retry-After sözbaşy, indiki backoff penjiresi).
Wagtlar we ölçegler
Baglanyşyk wagty ≤ 3-5 sek; jogabyň umumy wagty ≤ 10 sek.
Şertnama boýunça bedeniň ululygy (mysal üçin ≤ 256 KB), ýogsam 413 → "çunking" ýa-da "pull URL" logikasy.
4) Idempotentlik we duplikasiýa
Idempotent ulanmak: şol bir 'id' gaýtalamalaryny gaýtadan işlemek şol bir netijäni yzyna gaýtarmaly we ýagdaýy gaýtadan üýtgetmeli däldir.
Dap-ammar alyjynyň tarapynda: TTL processed_at retraý penjireleri bilen '(X-Webhook-Id, ≥, checksum)' saklamak (24-72 sagat).
Kompozisiýa açary: birnäçe topik bolsa → '(subscription_id, event_id)'.
5) Tertibi we "exactly-once effektleri"
Paýlanan ulgamlarda berk tertibi kepillendirmek kyn. Ulanyň:- Partition by key: şol bir logiki köplük (mysal üçin, 'order _ id') elmydama bir eltiş "kanalyna".
- Sequence: köne 'X-Webhook-Seq' bilen wakalary ret ediň we ýitirilenler gelmezden ozal "parking lot" -a goýuň.
- ulanylan amallaryň sanawy (outbox/inbox pattern),
- DB-de 'event _ id' boýunça geleşik upsert,
- çylşyrymly prosesler üçin sag/kompensasiýa.
6) Status-kodlar boýunça ýalňyşlyklary çözmek (tablisa)
7) Kanalyň howpsuzlygy
Her habaryň HMAC-yň goly; "wagt penjiresi" (mitm we replay-hüjümleri) bilen kabul edijini barlamak.
mTLS duýgur domenler üçin (KUS/tölegler).
Gidýän salgylaryň IP allowlist, TLS 1. 2+, HSTS.
PII-minimalizasiýa: goşmaça şahsy maglumatlary ibermäň; sahypalarda gizläň.
Syrlaryň aýlanmagy: hereket edýän iki açar (active/next) we häzirki açary görkezmek üçin "X-Key-Id" sözbaşy.
8) Nobatlar, DLQ we bellikler
Wakalar hökman iberijiniň tarapynda çykyş nobatynda/žurnalda ýazylýar (ygtybarly göçürme üçin).
Retraýlaryň iň ýokary derejesi geçende - waka sebäp bilen DLQ-e (Dead Letter Queue) gidýär.
Replay API (alyjy/operator üçin): RPS çäklendirmesi we goşmaça gol/ygtyýarnama bilen 'id '/wagt aralygy/tema boýunça gaýtadan ibermek.
POST /v1/webhooks/replay
{ "subscription_id": "sub_123", "from": "2025-11-03T00:00:00Z", "to": "2025-11-03T12:00:00Z" }
→ 202 Accepted
9) Şertnama we wersiýa
Wakany wersiýa ediň ('schema _ version') we ulag ('X-Webhook-Version').
Meýdanlary diňe goşmaça hökmünde goşuň; aýyrylanda - kiçi migrasiýa we geçiş döwri (dual-write).
Wakalaryň görnüşlerini, mysallaryny, shemalaryny (JSON Shema), ýalňyşlyk kodlaryny dokumentleşdiriň.
10) Synlamak we SLO
Iberijiniň esasy ölçegleri:- 'delivery _ success _ rate' (2xx/ähli synanyşyklar), 'first _ attempt _ success _ rate'
- `retries_total`, `max_retry_age_seconds`, `dlq_count`
- `latency_p50/p95` (occurred_at → ack_received_at)
- `ack_latency` (receive → 2xx), `processing_latency` (enqueue → done)
- `duplicates_total`, `invalid_signature_total`, `out_of_order_total`
99. Wakalaryň 9% -i ilkinji ACK ≤ 60 sek (28d) alýar.
- DLQ ≤ 0. umumy sanynyň 1%; DLQ ≤ 24 sagat.
11) Taýming we toruň döwülmegi
Wagt çäklerinde UTC ulanyň; NTP sinhronlaşdyryň.
'occurred _ at' -y iberiň we 'delivered _ at' -y goýuň.
Uzyn arakesmelerde/endpoint → toruny nobata goýuň, ösüşi çäklendiriň (backpressure + kwotalar).
12) Maslahat berlen çäkler we arassaçylyk
Abuna ýazylmak üçin RPS (mysal üçin 50 RPS, burst 100) + parallelizm (mysal üçin 10).
Maks. beden: 64-256 KB; has köp zat üçin - "notification + URL" we göçürip almak üçin gol.
'snake' -däki wakalaryň atlary. case 'ili' dot. type` (`order. created`).
Kabul edijiniň write-amallarynyň berk idempotentligi.
13) Mysallar: iberiji we alyjy
13. 1 Iberiji (psevdokod)
python def send_event(event, attempt=0):
body = json. dumps(event)
sig = hmac_sha256_base64(body, secret)
headers = {
"X-Webhook-Id": event["id"],
"X-Webhook-Seq": str(event["sequence"]),
"X-Retry": str(attempt),
"X-Signature": f"sha256={sig}",
"Content-Type": "application/json"
}
res = http. post(endpoint, body, headers, timeout=10)
if 200 <= res. status < 300:
mark_delivered(event["id"])
elif res. status == 410:
deactivate_subscription()
else:
schedule_retry(event, attempt+1) # backoff + jitter, respect 429 Retry-After
13. 2 Alyjy (ýalan resminama)
python
@app. post("/webhooks")
def handle():
body = request. data headers = request. headers assert verify_hmac(body, headers["X-Signature"], secret)
evt_id = headers["X-Webhook-Id"]
if dedup_store. exists(evt_id):
return, "" 204 enqueue_for_processing (body) # fast path. dedup_store put(evt_id, ttl=723600)
return, "" 202 # or 204
14) Synag we bulam-bujarlyk amallary
Negatiw ýagdaýlar: galyp däl gol, 429/5xx, wagt, 410, uly payload 'lar.
Özüni alyp baryş: out-of-order, dublikatlar, gijikdirmeler 1-10 minut, arakesme 24 sagat.
Iş ýüki: burst 10 ×; backpressure we DLQ durnuklylygyny barlaň.
Şertnamalar: JSON Shema, hökmany sözbaşylar, wakalaryň durnukly görnüşleri.
15) Girizmegiň çek-sanawy
- 2xx = ACK, we enqueue-den soň çalt gaýdyp gelmek
- Eksponensial backoff + jitter, hormat 'Retry-After'
- "X-Webhook-Id" (TTL ≥ retraý)
- HMAC gollary, syrlaryň aýlanmagy, optional mTLS
- DLQ + Replay API, gözegçilik we aladalar
- Çäklendirmeler: wagt, RPS, beden ululygy
- Sargyt: partition by key ýa-da 'sequence' + "parking lot"
- Resminamalar: shemalar, mysallar, ýalňyşlyklaryň kodowkalary, wersiýalary
- Bulam-bujarlyk synaglary: gijikdirmeler, goşa, toruň şowsuzlygy, uzak wagtlap replay
16) Mini-FAQ
Elmydama 200 jogap bermelimi?
Islendik 2xx üstünlik hasaplanýar. 202/204 - "nobata kabul edildi" üçin adaty tejribe.
Gaýtalanmagy bes edip bolarmy?
Hawa, 410 jogap we/ýa-da iberijiniň konsoly/API arkaly (abunalygy öçürmek).
Uly tölegler hakda näme aýdyp bilersiňiz?
"Bildiriş + secure URL" iberiň, göçürip almak üçin haýyşa gol çekiň we TTL guruň.
Tertibi nädip üpjün etmeli?
Partition by key + `sequence`; gapma-garşylykda - "parking lot" we täzeden oýnamak.
Jemi
Ygtybarly webhuklar - bu ACK (2xx) semantikasy, backoff + jitter bilen akylly gaýtalanmalar, berk idempotentlik we duplikasiýa, başarnykly howpsuzlyk (HMAC/mTLS), nobatlar + DLQ + bellikler we aç-açan gözegçilik. Şertnamany belläň, çäkleri we metrikleri giriziň, bulam-bujarlygy yzygiderli kowuň - ilkinji şowsuzlyklarda integrasiýalaryňyz "ýykylmagyny" bes eder.