Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Un codice di stato compreso tra 500 e 599 indica che il server non è riuscito a soddisfare una richiesta che sembrava valida. La richiesta non è il problema, quindi inviarla di nuovo può funzionare. Il fatto che sia necessario inviarla di nuovo dipende dal codice di stato e da ciò che comporta la richiesta. Per le definizioni, vedere RFC 9110, sezione 15.6.
Significato di ogni codice di stato
| Codice di stato | Che cosa significa | Riprova? |
|---|---|---|
500 Internal Server Error |
Il server ha raggiunto una condizione che non si aspettava | Dipende dall'API. Alcune API, come l'API Claude, indicano di ripetere un backoff esponenziale di 500. Controllare la documentazione dell'API. |
502 Bad Gateway |
Un gateway o un proxy ha ricevuto una risposta non valida dal server sottostante | Sì, se la richiesta è sicura da ripetere |
503 Service Unavailable |
Il server è temporaneamente sovraccaricato o inattivo per la manutenzione e dovrebbe essere ripristinato dopo qualche tempo. Il server può inviare un'intestazione Retry-After . |
Sì, dopo il Retry-After momento in cui il server ne ha inviato uno |
504 Gateway Timeout |
Un gateway o un proxy non ha ottenuto una risposta nel tempo dal server dietro di esso | Sì, se la richiesta è sicura da ripetere. Il gateway ha smesso di aspettare, quindi non si sa se il server ha eseguito il lavoro. |
Quali richieste sono sicure per riprovare
RFC 9110 chiama un metodo idempotente quando si invia la stessa richiesta più volte ha lo stesso effetto dell'invio una sola volta.
GET, HEAD, TRACE, PUT, DELETE e OPTIONS sono idempotenti.
POST e PATCH non sono. In base alla RFC, un client non deve ripetere automaticamente una richiesta con un metodo non idempotente, a meno che non sappia che la richiesta è comunque idempotente oppure possa stabilire che il server non ha mai applicato la richiesta originale. Per dettagli, vedere metodi idempotenti.
Un POST ritentato dopo un 502 o 504 può creare un secondo ordine o inviare un secondo messaggio di posta elettronica. Alcune librerie di retry ritentano ogni metodo per impostazione predefinita. Ad esempio, il gestore di resilienza standard .NET riprova POST a meno che non si invochi options.Retry.DisableForUnsafeHttpMethods(). Per informazioni dettagliate, vedere Creare app HTTP resilienti.
Retry-After in caso di 503
Un valore 503 può includere un'intestazione Retry-After . Il valore è o un numero di secondi, ad esempio 120, o una data HTTP, ad esempio Fri, 31 Dec 1999 23:59:59 GMT. Il codice deve gestire entrambi. Per informazioni dettagliate, vedere Retry-After.
Smetti di chiamare un'API che continua a non funzionare
I tentativi consentono di risolvere gli errori temporanei. Quando un'API è inattiva per pochi minuti, riprovare a ogni richiesta aggiunge carico a un server già in difficoltà e gli utenti aspettano il fallimento di ogni nuovo tentativo. Un circuit breaker tiene traccia degli errori e, quando sono presenti troppi errori, smette di chiamare l'API per un po' e fallisce immediatamente. Dopo questo periodo di tempo, consente di eseguire alcune richieste per verificare se l'API è stata ripristinata. Per altre informazioni, vedere pattern Circuit Breaker. Il .NET handler di resilienza standard include un circuit breaker che si apre per 5 secondi quando almeno il 10% delle richieste ha esito negativo in una finestra di 30 secondi con almeno 100 richieste.
Come gestire gli errori 5xx
- Riprovare gli errori 502, 503 e 504 solo per le richieste idempotenti. Per
POSTePATCH, riprovare solo se l'API documenta un modo per renderli sicuri da ripetere. - Attendere prima di riprovare. Usare
Retry-Afterquando il server lo invia. In caso contrario, usare il backoff esponenziale con jitter casuale e arrestarsi dopo alcuni tentativi. - Leggere la documentazione dell'API per 500. Riprovare solo se l'API dice che è sicura.
- Smetti di chiamare un'API che continua a fallire. Usare un circuit breaker in modo che l'app fallisca rapidamente durante il ripristino dell'API.
- Indicare all'utente cosa è successo. Mostra "il servizio presenta problemi, riprova più tardi" anziché un errore generico o uno stack trace.
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));
}
}
Come verificare che l'app gestisca gli errori 5xx
Raramente viene visualizzato un valore 5xx durante lo sviluppo e non puoi far fallire un'API su richiesta. Il modo in cui si testa decide se trovi i bug prima che lo facciano i tuoi utenti.
| Avvicinarsi | Cosa trovi | Quello che ti manca |
|---|---|---|
| Attendere l'ambiente di produzione | Interruzioni effettive | Tutto, fino a quando un utente non lo preme |
| Simula l'API nei test o consenti all'agente di codifica di scrivere il mock | Se il ramo di errore viene eseguito | Il client HTTP reale e la libreria di retry, e quante volte riprova effettivamente. L'app richiede anche un'opzione di sola prova per raggiungere il mock. |
| Chiamare l'API reale e attendere che fallisca | Comportamento reale | Non è possibile fare in modo che l'API fallisca a comando |
| Intercetta il traffico reale dell'app e restituisci errori 5xx alla frequenza desiderata | Il tuo vero client HTTP, libreria di retry e circuit breaker | Niente nella tua app cambia, quindi non testa il tuo codice in isolamento. Mantieni i test unitari per quello. |
Provalo nella tua app
Dev Proxy intercetta le richieste dell'app e ne fa fallire una parte con gli errori definiti, usando GenericRandomErrorPlugin. L'app continua a chiamare l'URL reale. Aggiungere il plug-in al file di configurazione e impostare il relativo errorsFile su un file con gli errori 5xx. Questo esempio usa https://api.contoso.com. Sostituiscilo con l'URL dell'API che la tua app chiama.
File: 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 }
]
}
]
}
Per impostazione predefinita, il plug-in fallisce il 50% delle richieste. Controlla nell'output di Dev Proxy che l'app ripeta le richieste GET e invii ciascun POST una sola volta. Dev Proxy non verifica se l'app attende Retry-After in caso di 503, quindi confronta manualmente i tempi di richiesta. Avviare quindi Dev Proxy con --failure-rate 100 per vedere cosa fa l'app quando l'API continua a non funzionare. Per altre informazioni, vedere Tasso di errore delle richieste di modifica. Per installare Dev Proxy, vedere Configurare Dev Proxy.