500, 502, 503 und 504 Fehler von APIs: Was sie bedeuten und wie man mit ihnen umgeht

Ein Statuscode von 500 bis 599 bedeutet, dass der Server eine gültige Anforderung nicht erfüllen konnte. Ihre Anfrage ist nicht das Problem, also kann es funktionieren, sie erneut zu senden. Ob Sie es erneut senden sollten, hängt vom Statuscode und davon ab, was die Anfrage bewirkt. Die Definitionen finden Sie unter RFC 9110, Abschnitt 15.6.

Was jeder Statuscode bedeutet

Statuscode Was dies bedeutet Erneut versuchen?
500 Internal Server Error Der Server ist auf einen unerwarteten Zustand gestoßen. Dies hängt von der API ab. Einige APIs, z. B. die Claude-API, teilen Ihnen mit, eine 500 mit exponentiellem Backoff erneut zu versuchen. Überprüfen Sie die API-Dokumentation.
502 Bad Gateway Ein Gateway oder Proxy hat eine ungültige Antwort vom Server dahinter erhalten. Ja, wenn die Anforderung sicher wiederholt werden kann
503 Service Unavailable Der Server ist vorübergehend überlastet oder wegen Wartungsarbeiten nicht verfügbar, und er sollte sich nach einiger Zeit wieder erholen. Der Server kann einen Retry-After Header senden. Ja, nach dem Retry-After Zeitpunkt, wenn der Server einen Zeitstempel gesendet hat
504 Gateway Timeout Ein Gateway oder Proxy hat nicht rechtzeitig vom dahinterliegenden Server eine Antwort erhalten. Ja, wenn die Anfrage sicher wiederholt werden kann. Das Gateway hat das Warten aufgegeben, sodass Sie nicht wissen, ob der Server die Arbeit ausgeführt hat.

Welche Anfragen sicher erneut versucht werden können

RFC 9110 bezeichnet eine Methode als idempotent, wenn das mehrmalige Senden derselben Anfrage die gleiche Wirkung hat wie das einmalige Senden. GET, HEAD, OPTIONS, TRACE, PUT und DELETE sind idempotent. POST und PATCH sind nicht. Laut RFC sollte ein Client eine Anforderung bei einer Anfrage mit einer nicht-idempotenten Methode nicht automatisch wiederholen, es sei denn, er weiß, dass die Anforderung trotzdem idempotent ist, oder er kann feststellen, dass der Server die ursprüngliche Anforderung nie angewendet hat. Ausführliche Informationen finden Sie unter Idempotent-Methoden.

Ein Wiederholungsversuch POST nach 502 oder 504 kann eine zweite Bestellung erstellen oder eine zweite E-Mail senden. Einige Wiederholungsbibliotheken wiederholen standardmäßig jede Methode. Beispielsweise wiederholt der .NET-Standardresilienzhandler den Vorgang POST, es sei denn, Sie rufen options.Retry.DisableForUnsafeHttpMethods() auf. Ausführliche Informationen finden Sie unter Resiliente HTTP-Apps erstellen.

Retry-After bei einem 503-Fehler

Ein 503 kann einen Retry-After Header enthalten. Der Wert ist entweder eine Anzahl von Sekunden, z. B. 120, oder ein HTTP-Datum, z. B. Fri, 31 Dec 1999 23:59:59 GMT. Ihr Code muss beide behandeln. Weitere Informationen finden Sie unter Retry-After.

Beenden Sie das Aufrufen einer API, die immer wieder fehlschlägt

Wiederholungsversuche helfen bei kurzzeitigen Ausfällen. Wenn eine API für Minuten nicht verfügbar ist, erhöht das erneute Wiederholen jeder Anforderung die Last auf einem Server, der bereits Probleme hat, und Ihre Benutzer warten, bis jeder erneute Versuch fehlschlägt. Ein Circuit Breaker verfolgt Fehler, und wenn zu viele Fehler auftreten, setzt er API-Aufrufe für eine Weile aus und schlägt sofort fehl. Nach diesem Zeitpunkt können einige Anfragen durchlaufen werden, um zu überprüfen, ob die API wiederhergestellt wurde. Weitere Informationen finden Sie unter Circuit-Breaker-Muster. Der .NET Standardresilienzhandler enthält einen Circuit Breaker, der sich für 5 Sekunden öffnet, wenn mindestens 10 % der Anforderungen in einem 30-Sekunden-Fenster mit mindestens 100 Anforderungen fehlschlagen.

Behandeln von 5xx-Fehlern

  1. Wiederholen Sie Anfragen mit 502, 503 und 504 nur bei idempotenten Anfragen. POST und PATCH nur dann wiederholen, wenn die API-Dokumentation beschreibt, wie sie sicher wiederholt werden können.
  2. Warten Sie, bevor Sie es erneut versuchen. Verwenden Sie Retry-After, wenn der Server es sendet. Verwenden Sie andernfalls exponentielle Backoffs mit zufälligem Jitter, und hören Sie nach einigen Versuchen auf.
  3. Lesen Sie die Dokumentation der API für HTTP 500. Versuchen Sie es nur dann erneut, wenn die API besagt, dass dies sicher ist.
  4. Rufen Sie eine API, die weiterhin fehlschlägt, nicht weiter auf. Verwenden Sie einen Circuit Breaker, damit Ihre App schnell fehlschlägt, während die API wiederhergestellt wird.
  5. Teilen Sie dem Benutzer mit, was passiert ist. Zeigen Sie „Der Dienst hat Probleme. Versuchen Sie es später erneut.“ anstelle eines generischen Fehlers oder einer Stacktrace an.
const RETRYABLE_STATUS = new Set([502, 503, 504]);
const IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE"]);

function retryAfterMs(response) {
  const value = response.headers.get("retry-after");
  if (!value) return null;
  const seconds = Number(value);
  if (Number.isFinite(seconds)) return seconds * 1000;
  const date = Date.parse(value);
  return Number.isNaN(date) ? null : Math.max(0, date - Date.now());
}

export async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  const method = (options.method ?? "GET").toUpperCase();
  const canRetry = IDEMPOTENT_METHODS.has(method);

  for (let attempt = 0; ; attempt++) {
    const response = await fetch(url, options);
    if (!RETRYABLE_STATUS.has(response.status) || !canRetry || attempt === maxRetries) {
      return response;
    }
    await response.body?.cancel();
    const backoff = 2 ** attempt * 1000 + Math.random() * 1000;
    const wait = retryAfterMs(response) ?? backoff;
    await new Promise((resolve) => setTimeout(resolve, wait));
  }
}

So testen Sie, dass Ihre App 5xx-Fehler behandelt

Während der Entwicklung sieht man selten einen 5xx-Fehler, und man kann eine API nicht gezielt fehlschlagen lassen. Die Art und Weise, wie Sie testen, entscheidet, ob Sie die Fehler finden, bevor Ihre Benutzer dies tun.

Approach Was Sie finden Was Ihnen fehlt
Warten auf Produktion Tatsächliche Ausfälle Alles, bis ein Benutzer darauf klickt
Mocken Sie die API in Ihren Tests oder lassen Sie Ihren Coding-Agenten den Mock schreiben Ob Ihr Fehlerzweig ausgeführt wird Der echte HTTP-Client und die Retry-Bibliothek und wie oft tatsächlich erneut versucht wird. Ihre App benötigt außerdem einen reinen Testschalter, um den Mock zu erreichen.
Rufen Sie die echte API auf, und warten Sie, bis die API fehlschlägt. Tatsächliches Verhalten Sie können die API nicht absichtlich zum Fehlschlagen bringen
Fangen Sie den tatsächlichen Datenverkehr Ihrer App ab und geben 5xx-Fehler mit einer von Ihnen ausgewählten Rate zurück. Der echte HTTP-Client, die Retry-Bibliothek und der Circuit Breaker Nichts in Ihrer App ändert sich, sodass Ihre App Ihren Code nicht isoliert testet. Halten Sie die Unit-Tests dafür.

Probieren Sie sie in Ihrer App aus

Dev Proxy fängt die Anforderungen Ihrer App ab und lässt einen Teil davon mit den von Ihnen definierten Fehlern fehlschlagen, indem das GenericRandomErrorPlugin verwendet wird. Ihre App ruft weiterhin die echte URL auf. Fügen Sie das Plug-In zu Ihrer Konfigurationsdatei hinzu, und verweisen Sie mit seinem errorsFile auf eine Datei mit den 5xx-Fehlern. In diesem Beispiel wird https://api.contoso.com verwendet. Ersetzen Sie sie durch die URL der API, die Ihre App aufruft.

Datei: server-errors.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.contoso.com/*"
      },
      "responses": [
        { "statusCode": 500 },
        { "statusCode": 502 },
        {
          "statusCode": 503,
          "headers": [
            { "name": "Retry-After", "value": "10" }
          ]
        },
        { "statusCode": 504 }
      ]
    }
  ]
}

Standardmäßig schlägt das Plug-In bei 50 % der Anfragen fehl. Überprüfen Sie in der Dev Proxy-Ausgabe, dass Ihre App GET-Anfragen wiederholt und jede POST nur einmal sendet. Dev Proxy überprüft nicht, ob Ihre App bei einer 503 auf Retry-After wartet. Vergleichen Sie daher die Anforderungszeiten selbst. Starten Sie dann Dev Proxy mit --failure-rate 100, um zu sehen, was Ihre App tut, wenn die API weiterhin fehlschlägt. Weitere Informationen finden Sie unter Fehlerrate bei Änderungsanfragen. Informationen zum Installieren von Dev Proxy finden Sie unter Einrichten von Dev Proxy.

Nächste Schritte

Siehe auch