Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Um código de status de 500 a 599 significa que o servidor falhou ao atender a uma solicitação que parecia válida. Sua solicitação não é o problema, portanto, enviá-la novamente pode funcionar. A decisão de reenviá-lo depende do código de status e do que a solicitação faz. Para obter as definições, consulte RFC 9110, seção 15.6.
O que significa cada código de status
| Código de status | O que significa | Tentar novamente? |
|---|---|---|
500 Internal Server Error |
O servidor encontrou uma condição inesperada | Depende da API. Algumas APIs, como a Claude API, dizem para você tentar novamente um 500 com backoff exponencial. Verifique a documentação da API. |
502 Bad Gateway |
Um gateway ou proxy recebeu uma resposta inválida do servidor por trás dele | Sim, se a solicitação for segura para repetir |
503 Service Unavailable |
O servidor está temporariamente sobrecarregado ou inoperante para manutenção e deve se restabelecer após algum tempo. O servidor pode enviar um cabeçalho Retry-After. |
Sim, após o horário Retry-After, se o servidor tiver enviado algum |
504 Gateway Timeout |
Um gateway ou proxy não recebeu uma resposta a tempo do servidor por trás dele | Sim, se a solicitação for segura de repetir. O gateway desistiu de esperar, por isso você não sabe se o servidor fez o trabalho. |
Quais solicitações são seguras para tentar novamente
A RFC 9110 considera um método idempotente quando enviar a mesma solicitação várias vezes tem o mesmo efeito que enviá-la uma vez.
GET, HEAD, OPTIONS, TRACE, PUT e DELETE são idempotentes.
POST e PATCH não são. De acordo com o RFC, um cliente não deve repetir automaticamente uma solicitação com um método não idempotente, a menos que saiba que a solicitação é idempotente de qualquer maneira ou pode dizer que o servidor nunca aplicou a solicitação original. Para obter detalhes, consulte métodos idempotentes.
Uma nova tentativa POST após um 502 ou 504 pode criar um segundo pedido ou enviar um segundo email. Algumas bibliotecas de repetição repetem todos os métodos por padrão. Por exemplo, o manipulador de resiliência padrão .NET tenta novamentePOST, a menos que você chame options.Retry.DisableForUnsafeHttpMethods(). Para obter detalhes, consulte Build resilient HTTP apps.
Retry-After em um 503
Um 503 pode incluir um cabeçalho Retry-After. Seu valor é ou um número de segundos, como 120, ou uma data HTTP, como Fri, 31 Dec 1999 23:59:59 GMT. Seu código precisa lidar com ambos. Para obter detalhes, consulte Retry-After.
Parar de chamar uma API que continua falhando
Tentativas ajudam com falhas breves. Quando uma API fica inativa por minutos, tentar novamente cada solicitação adiciona carga a um servidor que já está em dificuldades, e seus usuários esperam cada nova tentativa falhar. Um circuit breaker rastreia falhas e, quando há muitas, ele para de chamar a API por um tempo e falha imediatamente. Depois desse tempo, ele permite a passagem de algumas solicitações para verificar se a API se recuperou. Para obter mais informações, consulte padrão Circuit Breaker. O handler de resiliência padrão do .NET inclui um circuit breaker que é aberto por 5 segundos quando pelo menos 10% das solicitações falham em uma janela de 30 segundos com pelo menos 100 solicitações.
Como lidar com erros 5xx
- Tente novamente em caso de erro 502, 503 e 504 somente para solicitações idempotentes. Para
POSTePATCH, tente novamente somente se a API documentar uma maneira de torná-los seguros para repetir. - Aguarde antes de tentar novamente. Use
Retry-Afterquando o servidor o enviar. Caso contrário, use recuo exponencial com jitter aleatório e pare após algumas tentativas. - Leia os documentos da API para 500. Tente novamente somente se a API disser que é seguro.
- Pare de chamar uma API que continua falhando. Use um circuit breaker para que seu aplicativo falhe rapidamente enquanto a API se recupera.
- Diga ao usuário o que aconteceu. Mostrar "o serviço está tendo problemas, tente novamente mais tarde" em vez de um erro genérico ou um rastreamento de pilha.
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));
}
}
Como testar se seu aplicativo lida com erros 5xx
Você raramente vê um 5xx enquanto desenvolve e não pode fazer uma API falhar sob demanda. A maneira como você testa determina se você encontra os bugs antes que seus usuários os encontrem.
| Approach | O que você encontra | Do que você sente falta |
|---|---|---|
| Aguardar a produção | Indisponibilidades reais | Tudo, até que um usuário clique nele |
| Mockar a API em seus testes ou deixar seu agente de codificação escrever a simulação | Se o branch de erro ser executado | Seu cliente HTTP real e biblioteca de novas tentativas, e quantas vezes ele realmente faz novas tentativas. Seu aplicativo também precisa de uma opção somente de teste para acessar o mock. |
| Chamar a API real e esperar que ela falhe | Comportamento real | Você não pode fazer a API falhar quando quiser |
| Interceptar o tráfego real do aplicativo e retornar erros 5xx a uma taxa escolhida | Seu cliente HTTP real, biblioteca de retentativas e circuit breaker | Nada no app muda, portanto, ele não testa seu código isoladamente. Deixe isso para os testes unitários. |
Experimente em seu aplicativo
O Proxy de Desenvolvimento intercepta as solicitações do aplicativo e faz com que parte delas falhe com os erros definidos, usando o GenericRandomErrorPlugin. Seu aplicativo continua chamando a URL real. Adicione o plug-in ao arquivo de configuração e aponte seu errorsFile para um arquivo com os erros 5xx. Este exemplo usa https://api.contoso.com. Substitua-a pela URL da API que seu aplicativo usa.
Arquivo: 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 }
]
}
]
}
Por padrão, o plug-in faz com que 50% das solicitações falhem. Verifique na saída do Proxy de Desenvolvimento que seu aplicativo tenta novamente as solicitações GET e envia cada POST apenas uma vez. O Proxy de Desenvolvimento não verifica se o aplicativo aguarda Retry-After após um 503, portanto, compare você mesmo os tempos das solicitações. Em seguida, inicie o Proxy de Desenvolvimento com --failure-rate 100 para ver o que seu aplicativo faz quando a API continua falhando. Para obter mais informações, consulte Taxa de falha de solicitação de alteração. Para instalar o Dev Proxy, consulte Configurar o Dev Proxy.