Webhooks: Wiederholungen und Handshake
1) Grundlegendes Liefermodell
At-least-once (Standard): Das Ereignis wird ≥1 Mal geliefert. Garantien werden durch die Idempotenz des Empfängers genau einmal erreicht.
Handshake (ACK): Nur 2xx (normalerweise 200/204) vom Empfänger bedeutet Erfolg. Alles andere wird als Ablehnung interpretiert und führt zur Wiederholung.
Quick ACK: Antworten Sie 2xx, nachdem Sie das Ereignis der Reihe nach platziert haben, nicht nach einer vollständigen Geschäftsabwicklung.
2) Veranstaltungsformat und Pflichtüberschriften
Nutzlast (Beispiel)
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
}
Absendertitel
'X-Webhook-Id: evt_01HXYZ' - eindeutige Ereignis-ID (für Deduplizierung verwenden).
'X-Webhook-Seq: 128374' ist eine monotone Sequenz (nach Abonnement/Thema).
`X-Signature: sha256=<base64(hmac_sha256(body, secret))>` — HMAC-подпись.
'X-Retry: 0,1,2...' ist die Nummer des Versuchs.
„X-Webhook-Version: 1“ - Versionierung des Vertrages.
(optional) 'Traceparent' - Korrelation der Spuren.
Antwort des Empfängers
2xx - erfolgreich angenommen (es wird keine weiteren Wiederholungen für diese' id 'geben).
410 Gone - Endpoint gelöscht/inaktiv → Absender stoppt Wiederholungen und deaktiviert das Abonnement.
429/5xx/timeout - der Absender wiederholt die Retrace-Politik.
3) Politik der Wiederholung (retries)
Empfohlene Treppe backoff (+ jitter)
'1s, 3s, 10s, 30s, 2m, 10m, 30m, 2h, 6h, 24h' (wir stoppen nach einem Limit, zum Beispiel 48-72 Stunden).
Regeln:- Exponentieller Backoff + zufälliger Jitter (± 20-30%), um den „Herdeneffekt“ zu vermeiden.
- Fehlerquorum bei temporären Ausfällen (z.B. Wiederholung bei 5xx oder Netzwerk-Timeout).
- Respect 429: Minimum 'min (Retry-After-Header, nächstes Backoff-Fenster)' setzen.
Timeouts und Größen
Zeitüberschreitung der Verbindung ≤ 3-5 Sekunden; Gesamtzeitraum der Antwort ≤ 10 Sek.
Die Körpergröße steht unter Vertrag (z. B. ≤ 256 KB), ansonsten → 413 die Logik von „chunking“ oder „pull URL“.
4) Idempotenz und Deduplizierung
Idempotente Anwendung: Die Verarbeitung von Wiederholungen desselben 'id' sollte das gleiche Ergebnis zurückgeben und den Zustand nicht erneut ändern.
Dedup-Speicher auf der Empfängerseite: Speichern Sie'(X-Webhook-Id, processed_at, checksum) 'mit TTL ≥ Retrayfenster (24-72 h).
Kompositionsschlüssel: wenn mehrere Spitzen →'(subscription_id, event_id)'.
5) Ordnung und „exactly-once Effekte“
Die Gewährleistung einer strengen Ordnung ist in verteilten Systemen schwierig. Verwenden Sie:- Partition by key: die gleiche logische Menge (z.B. 'order _ id') immer in den gleichen „Kanal“ der Lieferung.
- Sequenz: Ereignisse mit der alten 'X-Webhook-Seq' ablehnen und in ein 'Parkhaus' setzen, bevor die Fehlenden ankommen.
- Protokoll der angewendeten Operationen (Outbox/Inbox-Muster),
- Transaktions-Upsert durch 'event _ id' in der DB,
- Saga/Kompensation für komplexe Prozesse.
6) Fehlerbehebung durch Statuscodes (Tabelle)
7) Kanalsicherheit
HMAC-Signatur jeder Nachricht; Überprüfung am Empfänger mit „Zeitfenster“ (Mitm- und Replay-Attacken).
mTLS für sensible Domains (CUS/Payments).
IP-Allowliste ausgehender Adressen, TLS 1. 2+, HSTS.
PII-Minimierung: Senden Sie keine zusätzlichen persönlichen Daten; Maskieren Sie in den Protokollen.
Rotation der Geheimnisse: Zwei gültige Schlüssel (aktiv/weiter) und der Header 'X-Key-Id', um die aktuelle anzuzeigen.
8) Warteschlangen, DLQ und Replikate
Ereignisse werden notwendigerweise in die Ausgabewarteschlange/das Protokoll auf der Senderseite geschrieben (für zuverlässige Replikate).
Wenn das Maximum der Retrays überschritten wird, geht das Ereignis mit der Ursache in die DLQ (Dead Letter Queue).
Replay API (für Empfänger/Betreiber): Re-Upload nach 'id '/Zeitbereich/Thema, mit RPS-Einschränkung und zusätzlicher Signatur/Autorisierung.
POST /v1/webhooks/replay
{ "subscription_id": "sub_123", "from": "2025-11-03T00:00:00Z", "to": "2025-11-03T12:00:00Z" }
→ 202 Accepted
9) Vertrag und Version
Versionieren Sie das Ereignis (Feld 'schema _ version') und den Transport ('X-Webhook-Version').
Fügen Sie Felder nur als optional hinzu; während der Entfernung - Moll-Migration und Übergangszeit (Dual-Write).
Dokumentieren Sie Ereignistypen, Beispiele, Schemata (JSON Schema), Fehlercodes.
10) Beobachtbarkeit und SLO
Wichtige Senderkennzahlen:- 'delivery _ success _ rate' (2xx/alle Versuche), '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. 9% der Ereignisse erhalten das erste ACK ≤ 60 Sekunden (28d).
- DLQ ≤ 0. 1% der Gesamtzahl; DLQ-Replikation ≤ 24 Stunden
11) Timing und Netzwerkbrüche
Verwenden Sie UTC in Zeitfeldern; Synchronisieren Sie NTP.
Senden Sie' occurred _ at 'und schreiben Sie' delivered _ at', um den Lag zu zählen.
Bei längeren Unterbrechungen des Netzwerks/Endpunkts → in der Warteschlange ansammeln, das Wachstum begrenzen (Backpressure + Quoten).
12) Empfohlene Grenzwerte und Hygiene
RPS pro Abonnement (z.B. 50 RPS, Burst 100) + Parallelität (z.B. 10).
Max. Körper: 64-256 KB; für mehr - „notification + URL“ und Signatur zum Herunterladen.
Die Namen der Ereignisse in 'snake. case' oder 'dot. type` (`order. created`).
Strikte Idempotenz der Schreiboperationen des Empfängers.
13) Beispiele: Sender und Empfänger
13. 1 Absender (Pseudocode)
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 Empfänger (Pseudocode)
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) Test- und Chaos-Praktiken
Negativfälle: Unwahrscheinliche Unterschrift, 429/5xx, Timeout, 410, große payload 's.
Verhalten: Out-of-Order, Duplikate, Verzögerungen von 1-10 Minuten, 24 Stunden Pause.
Last: Burst 10 ×; Überprüfen Sie die Backpressions- und DLQ-Stabilität.
Verträge: JSON Schema, Pflichtüberschriften, stabile Veranstaltungstypen.
15) Checkliste Umsetzung
- 2xx = ACK, und schnelle Rückkehr nach enqueue
- Exponentieller Backoff + Jitter, Respekt vor 'Retry-After'
- Empfänger-Idempotenz und Dedup durch 'X-Webhook-Id' (TTL ≥ Retrai)
- HMAC Signaturen, Secret Rotation, optional mTLS
- DLQ + Replay API, Überwachung und Warnungen
- Einschränkungen: Timeouts, RPS, Körpergröße
- Reihenfolge: Partition nach Schlüssel oder 'sequence' + 'parking lot'
- Dokumentation: Diagramme, Beispiele, Fehlercodierungen, Versionen
- Chaos-Tests: Verzögerungen, Takes, Netzwerkausfall, lange Replay
16) Mini-FAQ
Muss ich immer 200 antworten?
Jeder 2xx zählt als Erfolg. 202/204 ist eine gängige Praxis für „in die Warteschlange genommen“.
Können Wiederholungen gestoppt werden?
Ja, Antwort 410 und/oder über die Konsole/API des Absenders (Abonnement deaktivieren).
Was ist mit den großen Payload's?
Senden Sie eine „Benachrichtigung + sichere URL“, unterschreiben Sie die Download-Anfrage und installieren Sie TTL.
Wie kann für Ordnung gesorgt werden?
Partition by key + `sequence`; wenn Divergenz - „Parkplatz Los“ und Überspielen.
Summe
Robuste Webhooks sind klare ACK-Semantik (2xx), sinnvolle Wiederholungen mit Backoff + Jitter, strikte Idempotenz und Deduplizierung, kompetente Sicherheit (HMAC/mTLS), Warteschlangen + DLQ + Replikate und transparente Beobachtbarkeit. Fixieren Sie Ihren Vertrag, geben Sie Limits und Metriken ein, fahren Sie regelmäßig Chaos-Szenarien ab - und Ihre Integrationen werden bei den ersten Ausfällen nicht mehr „fließen“.