API-Wiederholungsstrategien und Exponentieller Backoff: Bewährte Muster

Beherrschen Sie den exponentiellen Backoff mit vollständigem Jitter, Retry-After-Headern, Idempotenzschlüsseln und Circuit Breakern, und testen Sie dann Ihre API-Wiederholungslogik mit Apidog-Mocks.

INEZA Felin-Michel

INEZA Felin-Michel

31 August 2026

API-Wiederholungsstrategien und Exponentieller Backoff: Bewährte Muster

Apidog für Unternehmen

On-Premises Bereitstellung

SSO & RBAC

SOC 2 konform

Apidog Enterprise entdecken

Ihr API-Aufruf zur Zahlung ist um 2 Uhr morgens fehlgeschlagen. War es ein Netzwerkaussetzer, eine Ratenbegrenzung oder ein ausgefallener Server? Die Antwort entscheidet, ob ein Wiederholungsversuch die Transaktion rettet oder einen Kunden doppelt belastet.

Wiederholungsversuche sind das häufigste Resilienzmuster in verteilten Systemen und werden am häufigsten vermasselt. Eine Schleife um einen HTTP-Aufruf herum fühlt sich wie defensive Programmierung an. Falsch ausgeführt, verwandelt sie einen 30-sekündigen Ausfall in einen 30-minütigen, weil Tausende von Clients gleichzeitig auf einen kämpfenden Server einhämmern. Richtig ausgeführt, absorbieren Wiederholungsversuche temporäre Fehler so sauber, dass Ihre Benutzer sie nie bemerken.

Dieser Leitfaden behandelt die Wiederholungslogik, auf die Produktionssysteme angewiesen sind: welche Statuscodes wiederholt werden sollen, die exponentielle Backoff-Formel mit vollem Jitter, Retry-After-Header, Idempotenzschlüssel, Wiederholungsbudgets und Circuit Breaker. Sie erfahren auch, wie Sie die korrekte Funktion Ihres Clients beweisen, indem Sie 429er und 503er mit Apidog Mock-Servern simulieren, denn ein Wiederholungsmuster, das Sie nie an einem ausgefallenen Server getestet haben, ist eine Vermutung, kein Design. Teams, die Fintech-API-Wiederholungslogik entwickeln, lernen dies auf die teure Art; Sie müssen das nicht.

Warum naive Wiederholungsversuche Ausfälle verschlimmern

Stellen Sie sich einen Dienst vor, der 1.000 Anfragen pro Sekunde verarbeitet. Er stottert für fünf Sekunden. Jeder Client versucht sofort, dreimal pro Client, erneut. Ihre Nachfrage von 1.000 Anfragen pro Sekunde wird zu 4.000 Anfragen pro Sekunde, die auf einen bereits überlasteten Server abzielen. Er bricht komplett zusammen. Nun versucht jeder Client erneut.

Diese Rückkopplungsschleife hat einen Namen: ein Wiederholungssturm. Der synchronisierte Ansturm, wenn der Server zurückkehrt, ist die „thundering herd“ (donnernde Herde). Googles SRE-Buch weist in seinem Kapitel über die Behebung kaskadierender Ausfälle auf dieses Muster hin: Wiederholungsversuche ohne Backoff verstärken die Last genau dann, wenn das System es am wenigsten verkraften kann, und können einen Dienst lange nach Behebung des ursprünglichen Fehlers lahmlegen.

Zwei Designfehler verursachen die meisten Wiederholungsstürme:

Die Lösung ist nicht „nie wiederholen“. Die Lösung besteht darin, selektiv zu wiederholen, mit zunehmenden randomisierten Verzögerungen und mit einer festen Obergrenze, wie viel zusätzliche Last Ihre Wiederholungsversuche hinzufügen.

Diese Fehler wiederholen, niemals jene

Bevor jegliche Backoff-Berechnung zum Tragen kommt, benötigt Ihr Client eine Entscheidungstabelle. Das Wiederholen einer Anfrage, die der Server bereits als ungültig zurückgewiesen hat, verschwendet Kapazität und verschmutzt die Logs. Das Wiederholen eines temporären Fehlers ist der eigentliche Zweck.

Diese wiederholen:

Signal Bedeutung
429 Too Many Requests Sie haben ein Ratenlimit erreicht. Ziehen Sie sich zurück und kommen Sie langsamer wieder.
502 Bad Gateway Ein vorgelagerter Hop lieferte Müll. Oft temporär.
503 Service Unavailable Der Server ist überlastet oder startet neu.
504 Gateway Timeout Eine vorgelagerte Abhängigkeit war zu langsam.
Verbindungsabbrüche, DNS-Fehler, Socket-Timeouts Die Anfrage ist möglicherweise nie angekommen.

Ein 504 Gateway Timeout verdient besondere Beachtung: Der Ursprungsserver hat Ihre Anfrage möglicherweise bearbeitet, obwohl das Gateway das Warten aufgegeben hat. Diese Unterscheidung ist wichtig, sobald wir zur Idempotenz kommen.

Diese niemals wiederholen:

Signal Bedeutung
400 Bad Request Ihre Nutzlast ist fehlerhaft. Sie wird auch beim nächsten Mal fehlerhaft sein.
401 Unauthorized Ihre Anmeldeinformationen sind falsch oder abgelaufen. Token aktualisieren, nicht in einer Schleife festhängen.
403 Forbidden Ihnen fehlen die Berechtigungen. Ein erneuter Versuch wird diese nicht erteilen.
422 Unprocessable Entity Validierung fehlgeschlagen. Beheben Sie die Daten, nicht das Timing.

Die Regel: Wiederholen Sie, wenn der Fehler den Serverzustand oder das Netzwerk betrifft. Schlagen Sie schnell fehl, wenn der Fehler Ihre Anfrage betrifft. Ein 429er liegt dazwischen; er ist wiederholbar, aber auch ein Signal, dass Ihre gesamte Anfragerate überarbeitet werden muss, was ein Ratenbegrenzungsproblem ist, das vor jeder Wiederholungsschleife gelöst werden muss.

Die exponentielle Backoff-Formel und warum Jitter wichtig ist

Exponentieller Backoff bedeutet, dass jeder Wiederholungsversuch länger wartet als der vorherige, standardmäßig verdoppelnd:

delay = base * 2^retry_count

Mit einer Basis von 500 ms sind das 0,5s, 1s, 2s, 4s, 8s. Fügen Sie eine Obergrenze (z. B. 30 Sekunden) hinzu, damit Verzögerungen nicht zu Minuten werden:

delay = min(cap, base * 2^retry_count)

Dies löst das „Hämmern“-Problem, aber nicht das Synchronisationsproblem. Wenn 5.000 Clients gleichzeitig fehlschlagen, kehren bei einfachem exponentiellem Backoff alle 5.000 bei t=0,5s zurück, dann bei t=1s, dann bei t=2s. Immer noch Wellen. Immer noch eine Herde, nur eine höflichere.

Jitter unterbricht die Synchronisation durch Randomisierung der Verzögerung. Der AWS Architecture Blog hat die Zahlen in seiner Analyse zu exponentiellem Backoff und Jitter untersucht und konkurrierende Clients gegen eine umstrittene Ressource simuliert. Backoff ohne Jitter erzeugte immer noch gebündelte Spitzen von Aufrufen. Voller Jitter, der eine zufällige Verzögerung zwischen Null und der exponentiellen Obergrenze wählt, erzeugte sowohl die wenigsten Gesamtaufrufe als auch nahezu die kürzesten Abschlusszeiten:

delay = random_between(0, min(cap, base * 2^retry_count))

Dieses Ergebnis überrascht viele. Eine vollständige Randomisierung bis auf Null fühlt sich im Vergleich zu einem ordentlichen Verdopplungsplan schlampig an. Aber die gleichmäßige Verteilung der Clients über das Zeitfenster ist genau das, was die Serverlast konstant hält. Die AWS-Analyse testete auch „Equal Jitter“ (halb fest, halb zufällig) und „Decorrelated Jitter“; voller Jitter und Decorrelated Jitter lagen vorne, und voller Jitter ist am einfachsten korrekt zu implementieren. Verwenden Sie es als Ihr Standard-Wiederholungsmuster, es sei denn, Sie haben Messungen, die etwas anderes besagen.

Beachten Sie Retry-After, wenn der Server es Ihnen mitteilt

Backoff ist, wenn Ihr Client schätzt, wie lange er warten soll. Manchmal nimmt der Server die Schätzung ab. Der Retry-After-Header, definiert für 429er und 503er Antworten, enthält entweder eine Anzahl von Sekunden oder ein HTTP-Datum:

HTTP/1.1 429 Too Many Requests
Retry-After: 12

Wenn dieser Header vorhanden ist, überschreibt er Ihren berechneten Backoff. Der Server weiß, wann sein Ratenlimitfenster zurückgesetzt wird oder seine Wartung endet; Ihr exponentieller Zeitplan nicht. Clients, die Retry-After ignorieren, sind ein Grund, warum Anbieter von Drosselung zu vollständigen Sperren übergehen. Parsen Sie es, respektieren Sie es und wenden Sie trotzdem Ihre Obergrenze und maximale Wiederholungsanzahl an, damit ein feindlicher oder fehlerhafter Retry-After: 86400 Ihren Worker nicht für einen Tag aufhängen kann.

Idempotenz: die Voraussetzung für die Wiederholung von POST

Hier ist die Falle bei diesem 504er von vorhin. GET, PUT und DELETE sind vertraglich idempotent: Zweimaliges Senden hinterlässt das System im selben Zustand. POST ist es nicht. Wenn POST /v1/payments nach der Verarbeitung durch den Server ein Timeout hat, erzeugt Ihr Wiederholungsversuch eine zweite Zahlung. Herzlichen Glückwunsch, Sie haben eine Doppelbelastungsmaschine mit exzellenter Verfügbarkeit gebaut.

Die Lösung ist ein Idempotenzschlüssel: eine eindeutige, clientgenerierte ID (normalerweise eine UUID), die als Header bei jeder logischen Operation gesendet wird. Der Server speichert den Schlüssel mit der ersten Antwort und spielt diese gespeicherte Antwort für jede Duplikat-Anfrage ab. Stripes idempotente Anfragen funktionieren genau so, und die meisten Zahlungs- und Bereitstellungs-APIs sind dem gefolgt.

Zwei Regeln lassen Schlüssel funktionieren:

Wenn die API, die Sie aufrufen, keine Idempotenzschlüssel unterstützt, wiederholen Sie nicht-idempotente Schreibvorgänge nicht automatisch. Melden Sie den Fehler und lassen Sie einen Menschen oder einen Abgleichsjob entscheiden.

Wiederholungsbudgets und Circuit Breaker: der Notausstieg

Backoff bestimmt, wann Wiederholungsversuche stattfinden. Es begrenzt nicht, wie viele stattfinden. Während eines langen Ausfalls häufen selbst gut gejitterte Clients Wiederholungslast an, und geschichtete Wiederholungsversuche vervielfachen sich: Wenn Ihr API-Gateway 3 Mal wiederholt und Ihr Service-Client 3 Mal wiederholt, kann ein einziger Benutzerklick zu 9 Anfragen werden.

Zwei Mechanismen begrenzen den Schaden:

Wiederholungsbudgets. Anstelle von „3 Wiederholungsversuchen pro Anfrage“ erzwingen Sie „Wiederholungsversuche dürfen höchstens 10% zusätzliche Last hinzufügen“, gemessen über ein gleitendes Fenster. Wenn das Budget aufgebraucht ist, werden Fehler sofort zurückgegeben. Dies hält die Wiederholungsverstärkung begrenzt, egal wie viele Anfragen gleichzeitig fehlschlagen. Linkerd und Envoy bieten dies beide als erstklassige Konfiguration an.

Circuit Breaker. Verfolgen Sie die Fehlerrate pro nachgelagertem Dienst. Wenn sie einen Schwellenwert überschreitet, öffnet sich der Breaker: Aufrufe schlagen sofort fehl, ohne das Netzwerk zu berühren. Nach einer Abkühlphase testen einige Sondierungsanfragen, ob die Abhängigkeit wiederhergestellt ist, bevor der Breaker sich wieder schließt. Wo Backoff den Ansturm höflich verlangsamt, bricht der Breaker ihn ab. Jedes ernsthafte Wiederholungsdesign paart die beiden, denn Backoff allein sendet letztendlich immer noch jede Anfrage.

Ein produktionsreifes Beispiel in Python

Hier ist das gesamte Muster an einem Ort: filterung nach wiederholbaren Statuscodes, voller Jitter, Retry-After-Unterstützung, ein Idempotenzschlüssel und eine feste Wiederholungsobergrenze.

import random
import time
import uuid
import requests

RETRYABLE = {429, 502, 503, 504}
BASE = 0.5     # seconds
CAP = 30.0     # ceiling on any single delay
MAX_RETRIES = 5

def create_payment(payload):
    idempotency_key = str(uuid.uuid4())  # one key per logical payment
    headers = {"Idempotency-Key": idempotency_key}

    for retry_count in range(MAX_RETRIES + 1):
        try:
            resp = requests.post(
                "https://api.acmepay.com/v1/payments",
                json=payload, headers=headers, timeout=10,
            )
            if resp.status_code < 400:
                return resp.json()
            if resp.status_code not in RETRYABLE:
                resp.raise_for_status()  # 400/401/403/422: fail fast
            retry_after = resp.headers.get("Retry-After")
        except (requests.ConnectionError, requests.Timeout):
            retry_after = None  # network fault: fall through to backoff

        if retry_count == MAX_RETRIES:
            raise RuntimeError("payment failed after all retries")

        if retry_after and retry_after.isdigit():
            delay = min(CAP, float(retry_after))
        else:
            delay = random.uniform(0, min(CAP, BASE * 2 ** retry_count))
        time.sleep(delay)

Bemerkenswert: Der Schlüssel wird einmalig außerhalb der Schleife erstellt. Retry-After hat Vorrang vor dem berechneten Backoff, respektiert aber immer noch die Obergrenze. Nicht wiederholbare Statuscodes lösen sofort einen Fehler aus. Wenn Sie im JavaScript-Bereich sind, bietet die axios-retry-Bibliothek die gleiche Struktur mit retryCondition und retryDelay Hooks; die Entscheidungstabelle bleibt identisch.

Wie man Wiederholungsverhalten testet, bevor die Produktion es für Sie tut

Die meisten Teams liefern Wiederholungscode aus, der niemals seinen Fehlerpfad ausgeführt hat. Der glückliche Pfad wurde getestet; der 503er-Pfad wird zum ersten Mal während eines echten Ausfalls durchlaufen. Mit zwei Apidog-Funktionen können Sie es besser machen.

Fehler mit Mock-Servern simulieren. Apidogs Smart Mock ermöglicht es Ihnen, einen Endpunkt wie /v1/payments zu definieren und seine Antworten zu skripten. Lassen Sie ihn bei den ersten beiden Aufrufen 503 zurückgeben und beim dritten 200, oder geben Sie einen 429er mit Retry-After: 5 zurück, oder fügen Sie eine 15-sekündige Verzögerung hinzu, um Ihr Client-Timeout auszulösen. Richten Sie Ihren Client auf die Mock-URL und beobachten Sie, wie die Wiederholungsschleife jedes Szenario behandelt, ohne dass ein Produktionsvorfall erforderlich ist.

Client-Verhalten mit Testszenarien überprüfen. Apidog-Testszenarien verketten Anfragen mit Zusicherungen und Timing-Prüfungen. Erstellen Sie ein Szenario, das gegen Ihren fehlerhaften Mock feuert und zusichert, dass der Aufruf schließlich erfolgreich ist, die gesamte verstrichene Zeit innerhalb Ihres erwarteten Backoff-Bereichs liegt und genau eine Ressource erstellt wurde (was beweist, dass Ihr Idempotenzschlüssel seine Aufgabe erfüllt hat). Binden Sie das Szenario in CI ein, und Ihre Wiederholungslogik wird bei jedem Commit anstatt bei jedem Ausfall getestet.

Dies ist der Unterschied zwischen „wir haben Wiederholungsversuche hinzugefügt“ und „wir haben verifiziert, dass unser Client eine ratenbegrenzte, halb ausgefallene Abhängigkeit überlebt.“ Laden Sie Apidog kostenlos herunter, und Sie können innerhalb von etwa zehn Minuten einen fehlerhaften Mock-Server gegen Ihren Client laufen lassen.

FAQ

Sollte ich einen 429er wiederholen?

Ja, und es ist der einzige Status, bei dem der Server Ihnen normalerweise sagt, wie. Lesen Sie den Retry-After-Header und warten Sie mindestens so lange; greifen Sie auf exponentielles Backoff mit Jitter zurück, wenn der Header fehlt. Behandeln Sie wiederholte 429er auch als Signal, Ihre Anfragerate mit clientseitiger Drosselung oder Caching zu korrigieren, nicht als normalen Betrieb.

Was ist voller Jitter?

Voller Jitter wählt jede Wiederholungsverzögerung gleichmäßig zufällig zwischen Null und der exponentiellen Obergrenze: random(0, min(cap, base * 2^n)). Er verhindert synchronisierte Wiederholungswellen von vielen Clients. In den Simulationen von AWS übertraf er sowohl den einfachen Backoff als auch den Equal Jitter in Bezug auf die Gesamtzahl der Aufrufe und die Abschlusszeit, weshalb er der Standard in den AWS SDKs ist.

Ist es sicher, POST-Anfragen zu wiederholen?

Nur wenn die Anfrage in der Praxis idempotent ist, was bei POST bedeutet, einen Idempotenzschlüssel zu senden, den der Server dedupliziert. Ohne einen solchen kann ein Wiederholungsversuch nach einem Timeout eine Zahlung, Bestellung oder einen Datensatz duplizieren, da der Server die Anfrage, die Sie für fehlgeschlagen halten, möglicherweise bearbeitet hat. KI-Agenten, die Schreib-APIs aufrufen, stoßen ständig darauf; die Fehlerbehebungsmuster von Agenten sind die gleichen, die hier behandelt werden: geschlüsselte Schreibvorgänge, begrenzte Wiederholungsversuche und ein Circuit Breaker.

Wie oft sollte ich es versuchen?

Drei bis fünf Versuche beheben fast jeden temporären Fehler; darüber hinaus flachen die Erfolgsraten ab, während Last und Latenz weiter steigen. Kombinieren Sie die Obergrenze pro Anfrage mit einem globalen Wiederholungsbudget (zum Beispiel dürfen Wiederholungsversuche höchstens 10% zusätzlichen Datenverkehr hinzufügen), damit ein vollständiger Ausfall Ihre Last nicht vervielfachen kann. Wenn eine Abhängigkeit nach Ihrem letzten Wiederholungsversuch weiterhin nicht verfügbar ist, ist das Circuit-Breaker-Gebiet, nicht Wiederholungsgebiet.

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen