500-, 502-, 503- en 504-fouten van API's: wat ze betekenen en hoe ze moeten worden verwerkt

Een statuscode van 500 tot 599 betekent dat de server er niet in slaagde te voldoen aan een verzoek dat geldig leek. Uw aanvraag is niet het probleem, dus het opnieuw verzenden kan werken. Of u het opnieuw moet verzenden, is afhankelijk van de statuscode en van wat het verzoek doet. Zie RFC 9110, sectie 15.6 voor de definities.

Wat elke statuscode betekent

Statuscode Wat betekent het? Probeer het opnieuw?
500 Internal Server Error De server is in een onverwachte toestand beland Dit is afhankelijk van de API. Sommige API's, zoals de Claude-API, vertellen u dat u een verzoek dat een 500 oplevert opnieuw moet proberen met exponentiële backoff. Controleer de documentatie van de API.
502 Bad Gateway Een gateway of proxy heeft een ongeldig antwoord ontvangen van de server erachter Ja, als het verzoek veilig is om te herhalen
503 Service Unavailable De server is tijdelijk overbelast of offline voor onderhoud en zou na enige tijd moeten herstellen. De server kan een Retry-After header verzenden. Ja, na de Retry-After tijd als de server er een heeft verzonden
504 Gateway Timeout Een gateway of proxy heeft geen reactie op tijd ontvangen van de server daarachter Ja, als het verzoek veilig is om te herhalen. De gateway stopte met wachten, dus u weet niet of de server het werk deed.

Welke verzoeken veilig opnieuw kunnen worden geprobeerd

RFC 9110 noemt een methode idempotent wanneer het verzenden van dezelfde aanvraag meerdere keren hetzelfde effect heeft als het één keer verzenden. GET, HEAD, OPTIONS, TRACE, PUT en DELETE zijn idempotent. POST en PATCH zijn dat niet. Volgens de RFC moet een client een aanvraag niet automatisch opnieuw proberen met een niet-idempotente methode, tenzij deze weet dat de aanvraag toch idempotent is, of dat de server de oorspronkelijke aanvraag nooit heeft toegepast. Zie Idempotent-methoden voor meer informatie.

Een opnieuw geprobeerd POST na een 502- of 504-fout kan een tweede bestelling maken of een tweede e-mail verzenden. Sommige retry-bibliotheken voeren standaard elke methode opnieuw uit. Bijvoorbeeld, de .NET-standaardhandler voor tolerantie probeert POST opnieuw tenzij u options.Retry.DisableForUnsafeHttpMethods() aanroept. Zie Robuuste HTTP-apps bouwen voor details.

Retry-After op een 503

Een 503 kan een Retry-After header bevatten. De waarde is ofwel een aantal seconden, zoals 120, of een HTTP-datum, zoals Fri, 31 Dec 1999 23:59:59 GMT. Uw code moet beide afhandelen. Zie Retry-After voor meer informatie.

Stop met het aanroepen van een API die steeds faalt

Opnieuw proberen helpt bij tijdelijke storingen. Wanneer een API enkele minuten niet beschikbaar is, voegt elke nieuwe poging extra belasting toe aan een server die al moeite heeft, en wachten uw gebruikers totdat elke nieuwe poging mislukt. Een circuit breaker houdt fouten bij en wanneer er te veel zijn, wordt de API een tijdje niet meer aangeroepen en faalt het direct. Na die tijd laat het een paar verzoeken door om te controleren of de API is hersteld. Zie Circuit Breaker-patroon voor meer informatie. De .NET standaard-resiliencehandler bevat een circuitbreaker die gedurende vijf seconden open blijft wanneer ten minste 10% van de aanvragen mislukt in een periode van 30 seconden met ten minste 100 aanvragen.

Omgaan met 5xx-fouten

  1. Probeer aanvragen alleen opnieuw bij 502, 503 en 504 voor idempotente aanvragen. Probeer POST en PATCH alleen opnieuw als de API-documentatie een manier beschrijft om ze veilig te herhalen.
  2. Wacht voordat u het opnieuw probeert. Gebruik Retry-After wanneer de server het verzendt. Gebruik anders exponentiële wachttijd met willekeurige variatie, en stop na een paar pogingen.
  3. Lees de documentatie van de API voor 500. Probeer het alleen opnieuw als de API zegt dat deze veilig is.
  4. Stop met het aanroepen van een API waarvan aanroepen steeds mislukken. Gebruik een circuitonderbreker zodat uw app snel faalt terwijl de API wordt hersteld.
  5. Vertel de gebruiker wat er is gebeurd. Toon 'De service ondervindt problemen, probeer het later opnieuw' in plaats van een algemene fout of een stacktracering.
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));
  }
}

Hoe u kunt testen of uw app 5xx-fouten verwerkt

U ziet zelden een 5xx tijdens het ontwikkelen en u kunt een API niet op aanvraag laten mislukken. De manier waarop u test, bepaalt of u de bugs vindt voordat uw gebruikers dat doen.

Approach Wat u vindt Wat u mist
Wacht op productie Daadwerkelijke storingen Alles, tot een gebruiker erop klikt
Mock the API in your tests, or let your coding agent write the mock Of uw foutbranch wordt uitgevoerd Uw echte HTTP-client en bibliotheek voor opnieuw proberen, en hoe vaak het daadwerkelijk opnieuw wordt geprobeerd. Uw app heeft ook een testswitch nodig om de mock te bereiken.
De echte API aanroepen en wachten tot de aanroep mislukt Feitelijk gedrag U kunt de API niet op aanvraag laten mislukken
Het werkelijke verkeer van uw app onderscheppen en 5xx-fouten retourneren met een door u gekozen frequentie Uw echte HTTP-client, bibliotheek voor opnieuw proberen en circuitonderbreker Er verandert niets in uw app, dus uw code wordt niet geïsoleerd getest. Houd daar uw eenheidstests voor.

Probeer het in uw app

Dev Proxy onderschept de aanvragen van uw app en laat een deel ervan mislukken met de fouten die u definieert, met behulp van GenericRandomErrorPlugin. Uw app blijft de echte URL aanroepen. Voeg de invoegtoepassing toe aan uw configuratiebestand en wijs errorsFile naar een bestand met de 5xx-fouten. In dit voorbeeld wordt https://api.contoso.comgebruikt. Vervang deze door de URL van de API die door uw app wordt aangeroepen.

Bestand: 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 }
      ]
    }
  ]
}

Standaard laat de invoegtoepassing 50% van de aanvragen mislukken. Controleer in de uitvoer van de dev-proxy of uw app het bij GET-aanvragen opnieuw probeert en elke POST slechts één keer verzendt. Dev Proxy controleert niet of uw app bij een 503 op Retry-After wacht, dus vergelijk de aanvraagtijden zelf. Start vervolgens Dev Proxy met --failure-rate 100 om te zien wat uw app doet wanneer de API blijft falen. Zie Foutpercentage van wijzigingsaanvraag voor meer informatie. Om Dev Proxy te installeren, raadpleegt u Dev Proxy instellen.

Volgende stappen 

Zie ook