500, 502, 503 és 504 API-k hibái: mit jelentenek és hogyan kezelhetők

Az 500 és 599 közötti állapotkód azt jelenti, hogy a kiszolgáló nem tudott érvényesnek tűnő kérést teljesíteni. A kérés nem a probléma, ezért az újbóli elküldése működni fog. Az, hogy újra el kell-e küldenie, az állapotkódtól és attól függ, hogy mit tesz a kérés. A definíciókat lásd az RFC 9110 15.6. szakaszában.

Az egyes állapotkódok jelentése

Állapotkód Mit jelent ez? Próbálja újra?
500 Internal Server Error A kiszolgáló olyan feltételbe ütközött, amelyre nem számított Az API-tól függ. Egyes API-k, például a Claude API, azt mondják, hogy próbálkozzon újra egy 500-zal exponenciálisan növelt várakozási idővel. Ellenőrizze az API dokumentációját.
502 Bad Gateway Egy átjáró vagy proxy érvénytelen választ kapott a mögöttes kiszolgálótól Igen, ha a kérés biztonságosan megismételhető
503 Service Unavailable A kiszolgáló átmenetileg túlterhelt vagy le van terhelve karbantartás céljából, és egy idő után helyre kell állnia. A kiszolgáló küldhet fejlécet Retry-After . Igen, a Retry-After kiszolgáló által küldött idő után
504 Gateway Timeout Az átjáró vagy proxy nem kapott időben választ a mögöttes kiszolgálótól Igen, ha a kérést nyugodtan megismételheti. Az átjáró feladta a várakozást, így nem tudja, hogy a kiszolgáló végezte-e a munkát.

Mely kéréseket biztonságos újrapróbálni

Az RFC 9110 egy metódust idempotensnek nevez, ha ugyanannak a kérésnek a többszöri elküldése ugyanolyan hatással jár, mint az egyszeri elküldése. GET, HEAD, OPTIONS, TRACE, PUTés DELETE idempotensek. POST és PATCH nem is. Az RFC szerint az ügyfélnek nem szabad automatikusan újrapróbálkoznia egy nem idempotens metódusú kéréssel, hacsak nem tudja, hogy a kérés mégis idempotens, vagy azt is meg tudja állapítani, hogy a kiszolgáló soha nem alkalmazta az eredeti kérést. Részletekért lásd: Idempotens módszerek.

Egy 502-es vagy 504-es hiba után újrapróbált POST létrehozhat egy második megrendelést, vagy küldhet egy második e-mailt. Egyes újrapróbálkozási kódtárak alapértelmezés szerint minden metódust újrapróbálnak. A .NET standard rugalmasságkezelő például újrapróbálkozik POST, hacsak nem hívja meg options.Retry.DisableForUnsafeHttpMethods(). További részletekért lásd: Rugalmas HTTP-alkalmazások létrehozása.

Retry-After 503-on

Az 503-ak tartalmazhatnak fejlécet Retry-After . Az értéke vagy másodpercek száma, például 120egy HTTP-dátum, például Fri, 31 Dec 1999 23:59:59 GMT. A kódnak mindkettőt kezelnie kell. További részletekért lásd: Retry-After.

Hagyja abba a folyamatosan hibázó API hívását

Az újrapróbálkozások segítenek az átmeneti hibák elhárításában. Ha egy API percekig leáll, minden kérés újrapróbálkozása terhelést ad egy már amúgy is küszködő kiszolgálóhoz, és a felhasználók megvárják, hogy minden újrapróbálkozás kudarcot valljon. A circuit breaker nyomon követi a hibákat, és ha túl sok van, egy időre leállítja az API hívását, és azonnal hibát jelez. Ezután átenged néhány kérést, hogy ellenőrizze, helyreállt-e az API. További információkért lásd: áramkör-megszakító minta. A .NET szabványos rezilienciakezelője tartalmaz egy áramkörmegszakítót, amely 5 másodpercre megnyílik, ha egy 30 másodperces időablakban a kérések legalább 10%-a meghiúsul, legalább 100 kérés esetén.

5xx-hibák kezelése

  1. Csak idempotens kérések esetén próbálkozzon újra az 502-es, 503-as és 504-es hibákra. A PATCH és POST esetén csak akkor próbálkozzon újra, ha az API dokumentálja, hogyan tehetők azok biztonságosan megismételhetővé.
  2. Várjon, mielőtt újra próbálkozik. Használja Retry-After-t, amikor a kiszolgáló elküldi. Ellenkező esetben alkalmazzon exponenciálisan növekvő késleltetést véletlenszerű ingadozással, majd néhány próbálkozás után hagyja abba.
  3. Olvassa el az API 500-as dokumentációját. Csak akkor próbálja újra, ha az API azt mondja, hogy biztonságos.
  4. Ne hívjon tovább egy folyton hibázó API-t. Használjon circuit breaker mintát, hogy az alkalmazás azonnal hibát jelezzen, amíg az API helyreáll.
  5. Mondja el a felhasználónak, mi történt. "A szolgáltatással problémák vannak, próbálkozzon újra később" felirat jelenik meg általános hiba vagy veremkövetés helyett.
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));
  }
}

Annak tesztelése, hogy az alkalmazás kezeli-e az 5xx hibákat

Fejlesztés közben ritkán lát 5xx hibát, és nem lehet igény szerint hibára kényszeríteni az API-t. Az, ahogyan Ön tesztel, meghatározza, hogy Ön találja-e meg a hibákat, mielőtt a felhasználói találnák meg őket.

Approach Mit talál? Ami hiányzik
Várjon az éles üzemre Valós kimaradások Minden, amíg egy felhasználó rá nem kattint
Mockold az API-t a tesztekben, vagy hagyd, hogy a kódolási ügynök megírja a mockot Hogy lefut-e a hibaág A valódi HTTP-kliens és újrapróbálkozási kódtára, és hányszor próbálkozik újra. Az alkalmazásnak egy csak tesztelési kapcsolóra is szüksége van a mock eléréséhez.
Hívja meg a valódi API-t, és várja meg, amíg hibát jelez Valós viselkedés Az API-t nem lehet igény szerint hibára kényszeríteni
Fogja el alkalmazása valós forgalmát, és adjon vissza 5xx hibákat az Ön által választott arányban Az Ön valódi HTTP-kliense, újrapróbálkozási könyvtára és megszakító mintája Az alkalmazásban semmi sem változik, így nem teszteli a kódot elkülönítve. Arra valók az egységtesztek.

Próbálja ki az alkalmazásában

A Dev Proxy elfogja az alkalmazás kéréseit, és a GenericRandomErrorPlugin használatával az Ön által megadott hibákkal meghiúsít egy részüket. Az alkalmazás továbbra is az éles URL-t hívja. Adja hozzá a beépülő modult a konfigurációs fájlhoz, és állítsa a errorsFile elemét egy 5xx hibákat tartalmazó fájlra. Ez a példa a https://api.contoso.com-t használja. Cserélje le azt az alkalmazás által hívott API URL-címére.

Fájl: 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 }
      ]
    }
  ]
}

Alapértelmezés szerint a beépülő modul a kérések 50%-a meghiúsul. Ellenőrizze a Dev Proxy kimenetében, hogy az alkalmazás újrapróbálja-e a GET kéréseket, és hogy minden POST csak egyszer küld-e el. A Dev Proxy nem ellenőrzi, hogy az alkalmazás 503 esetén vár-e a Retry-After elemre, ezért hasonlítsa össze saját maga a kérések idejét. Ezután indítsa el a Dev Proxyt --failure-rate 100, hogy lássa, mit tesz az alkalmazás, ha az API folyamatosan hibázik. További információkért lásd a módosítási kérelmek sikertelenségi aránya ismertető témakört. A Dev Proxy telepítéséhez lásd: Dev Proxy beállítása.

További lépések

Lásd még