Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Un code d’état de 500 à 599 signifie que le serveur n’a pas pu répondre à une demande qui semblait valide. Votre demande n’est pas le problème, donc l’envoyer à nouveau peut fonctionner. Si vous devez l’envoyer à nouveau dépend du code d’état et de ce que fait la demande. Pour connaître les définitions, consultez RFC 9110, section 15.6.
Signification de chaque code d’état
| Code de statut | Ce que cela signifie | Réessayez ? |
|---|---|---|
500 Internal Server Error |
Le serveur a atteint une condition qu’il n’attendait pas | Cela dépend de l’API. Certaines API, comme l’API Claude, vous indiquent de réessayer après une erreur 500 en appliquant un délai exponentiel entre les tentatives. Consultez les documents de l’API. |
502 Bad Gateway |
Une passerelle ou un proxy a obtenu une réponse non valide du serveur derrière celui-ci | Oui, si la demande est sûre à répéter |
503 Service Unavailable |
Le serveur est temporairement surchargé ou arrêté pour maintenance, et il devrait redevenir accessible après un certain temps. Le serveur peut envoyer un en-tête Retry-After. |
Oui, après Retry-After l’heure si le serveur en a envoyé un |
504 Gateway Timeout |
Une passerelle ou un proxy n’a pas reçu de réponse à temps du serveur en amont | Oui, si la demande peut être répétée sans risque. La passerelle a cessé d’attendre. Vous ne savez donc pas si le serveur a effectué le travail. |
Quelles requêtes sont sécurisées pour réessayer
La RFC 9110 considère qu’une méthode est idempotente lorsque l’envoi de la même requête plusieurs fois a le même effet que son envoi une seule fois.
GET, HEAD, TRACE, OPTIONS, PUT et DELETE sont idempotents.
POST et PATCH ne le sont pas. Selon la RFC, un client ne doit pas réessayer automatiquement une demande avec une méthode non idempotente, sauf s’il sait que la requête est idempotente de toute façon, ou qu’il peut déterminer que le serveur n’a jamais appliqué la requête d’origine. Pour plus d’informations, consultez les méthodes idempotentes.
Une nouvelle tentative POST après un 502 ou 504 peut créer une deuxième commande ou envoyer un deuxième e-mail. Certaines bibliothèques de réessai réessaient chaque méthode par défaut. Par exemple, le gestionnaire de résilience standard .NET réessayePOST, sauf si vous appelez options.Retry.DisableForUnsafeHttpMethods(). Pour plus d’informations, consultez Créer des applications HTTP résilientes.
Retry-After dans une réponse 503
Un 503 peut inclure un en-tête Retry-After. Sa valeur est soit un nombre de secondes, par 120exemple, soit une date HTTP, comme Fri, 31 Dec 1999 23:59:59 GMT. Votre code doit gérer les deux. Pour plus d’informations, consultez Retry-After.
Arrêter l’appel d’une API qui continue d’échouer
Les réessais aident en cas d’échecs temporaires. Lorsqu’une API est en panne pendant des minutes, réessayer chaque requête ajoute une charge à un serveur déjà en difficulté, et vos utilisateurs attendent que chaque nouvelle tentative échoue. Un disjoncteur suit les défaillances et, lorsqu’il y a trop d’échecs, il cesse d’appeler l’API pendant un certain temps et échoue immédiatement. Après ce temps, il laisse passer quelques requêtes pour vérifier si l’API s’est rétablie. Pour plus d’informations, consultez le modèle Circuit Breaker. Le gestionnaire de résilience standard .NET inclut un disjoncteur qui s’ouvre pendant 5 secondes quand au moins 10% de requêtes échouent dans une fenêtre de 30 secondes avec au moins 100 requêtes.
Comment gérer les erreurs 5xx
- Réessayez les requêtes idempotentes uniquement en cas de code 502, 503 ou 504. Pour
POSTetPATCH, réessayez uniquement si l’API documente un moyen de garantir qu’ils peuvent être relancés sans risque. - Attendez avant de réessayer. Utilisez
Retry-Afterquand le serveur l’envoie. Sinon, utilisez un backoff exponentiel avec une gigue aléatoire et arrêtez après quelques tentatives. - Lisez la documentation de l’API pour l’erreur 500. Réessayez uniquement si l’API indique que cela est sans danger.
- Arrêtez d’appeler une API qui échoue constamment. Utilisez un circuit breaker pour que votre application échoue rapidement pendant que l’API se rétablit.
- Indiquez à l’utilisateur ce qui s’est passé. Affichez « le service rencontre des problèmes, réessayez ultérieurement » au lieu d’une erreur générique ou d’une trace de pile.
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));
}
}
Comment tester que votre application gère les erreurs 5xx
Vous voyez rarement un 5xx pendant que vous développez, et vous ne pouvez pas provoquer l’échec d’une API à la demande. La façon dont vous testez détermine si vous trouvez les bogues avant que vos utilisateurs ne le fassent.
| Approach | Ce que vous trouvez | Ce qui vous manque |
|---|---|---|
| Attendre la mise en production | Pannes réelles | Tout, jusqu’à ce qu’un utilisateur clique dessus |
| Simuler l’API dans vos tests ou laisser votre agent de codage écrire la simulation | Si votre branche d’erreur s’exécute | Votre client HTTP réel et votre bibliothèque de nouvelles tentatives, et combien de fois il retente réellement. Votre application a également besoin d’un commutateur uniquement pour les tests afin d’atteindre le mock. |
| Appelez l’API réelle et attendez qu’elle échoue | Comportement réel | Vous ne pouvez pas faire échouer l’API volontairement |
| Interceptez le trafic réel de votre application et retournez des erreurs 5xx à un débit que vous choisissez | Votre véritable client HTTP, bibliothèque de nouvelle tentative et coupe-circuit | Rien dans votre application ne change, de sorte que cela ne teste pas votre code de manière isolée. Conservez vos tests unitaires pour cela. |
Essayez-le dans votre application
Le proxy de développement intercepte les requêtes de votre application et fait échouer une partie d’entre elles avec les erreurs que vous définissez, à l’aide de GenericRandomErrorPlugin. Votre application continue d’appeler l’URL réelle. Ajoutez le plug-in à votre fichier de configuration et faites pointer son errorsFile vers un fichier contenant les erreurs 5xx. Cet exemple utilise https://api.contoso.com. Remplacez-le par l’URL de l’API que votre application appelle.
Fichier : 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 }
]
}
]
}
Par défaut, le plug-in échoue pour 50 % des requêtes. Vérifiez dans la sortie de Dev Proxy que votre application retente les requêtes GET et n’envoie chaque POST qu’une seule fois. Le proxy de développement ne vérifie pas si votre application attend Retry-After en cas de réponse 503, donc comparez vous-même les temps de requête. Démarrez ensuite Dev Proxy avec --failure-rate 100 pour voir ce que fait votre application lorsque l’API continue d’échouer. Pour plus d’informations, consultez Le taux d’échec des demandes de modification. Pour installer Dev Proxy, consultez Configurer Dev Proxy.
Étapes suivantes
Voir aussi
- Qu’est-ce que le test de chaos ?
- .NET délais d’expiration HttpClient : TaskCanceledException et TimeoutRejectedException
- 429 Trop de demandes : ce que cela signifie et comment le gérer
- Testez les nouvelles tentatives et les délais d’expiration dans les applications .NET qui utilisent Microsoft.Extensions.Http.Resilience