Diretrizes de repetição dos serviços do Azure

A maioria dos serviços do Azure e SDKs do cliente inclui um mecanismo de repetição. No entanto, eles são diferentes porque cada serviço apresenta características e requisitos diferentes, e cada mecanismo de repetição é ajustado para um serviço específico. Este guia resume os recursos do mecanismo de repetição para a maioria dos serviços do Azure, além de incluir informações que ajudam a usar, a adaptar ou a estender o mecanismo de repetição para o serviço em questão.

Para obter orientação geral sobre o tratamento de falhas transitórias e como repetir conexões e operações em serviços e recursos, consulte Diretriz de repetição.

A tabela a seguir resume os recursos de repetição para os serviços do Azure descritos nesta diretriz.

Serviço Recursos de repetição Configuração de política Escopo Recursos de telemetria
Microsoft Entra ID Nativo na biblioteca MSAL Inserido na biblioteca MSAL Interno Nenhum
Azure Cosmos DB Nativo no serviço Não configurável Global TraceSource
Data Lake Store Nativo no cliente Não configurável Operações individuais Nenhum
Hubs de Eventos Nativo no cliente Programático Cliente Nenhum
Hub IoT Nativo no cliente SDK Programático Cliente Nenhum
Cache Redis do Azure Nativo no cliente Programático Cliente TextWriter
Pesquisa Nativo no cliente Programático Cliente ETW ou Personalizado
Barramento de Serviço Nativo no cliente Programático Gerenciador de Namespace, Messaging Factory e Cliente ETW
Service Fabric Nativo no cliente Programático Cliente Nenhum
Banco de dados SQL com ADO.NET Polly Programático e declarativo Instruções ou blocos de código únicos Personalizado
Banco de dados SQL com o Entity Framework Nativo no cliente Programático Global por AppDomain Nenhum
Banco de dados SQL com Entity Framework Core Nativo no cliente Programático Global por AppDomain Nenhum
Storage Nativo no cliente Programático Operações individuais e de cliente TraceSource

Observação

Para a maioria dos mecanismos de repetição internos do Azure, atualmente não há meios de aplicar uma política de repetição diferente para diversos tipos de erro ou exceção. Você deve configurar uma política que fornece o melhor desempenho médio e disponibilidade. Uma maneira de ajustar a política é analisar arquivos de log para determinar o tipo de falha transitória que está ocorrendo.

Microsoft Entra ID

O Microsoft Entra ID é uma solução abrangente de nuvem para gerenciamento de acesso e identidade que combina serviços principais de diretório, governança avançada de identidade, segurança e gerenciamento de acesso a aplicativos. O Microsoft Entra ID também oferece aos desenvolvedores uma plataforma de gerenciamento de identidade para fornecer controle de acesso aos respectivos aplicativos, com base nas regras e políticas centralizadas.

Observação

Para obter diretrizes sobre a repetição em pontos de extremidade de identidade de serviço gerenciado, veja como usar uma MSI (Identidade de Serviço Gerenciada) de VM do Azure para aquisição de token.

Mecanismo de repetição

Na MSAL (Biblioteca de Autenticação da Microsoft) há um mecanismo interno de repetição para o Microsoft Entra ID. Para evitar bloqueios inesperados, recomendamos que a MSAL lide com as repetições e não permita que as bibliotecas de terceiros ou o código do aplicativo repitam as conexões com falhas.

Diretriz de uso de repetição

Considere as seguintes diretrizes ao usar o Microsoft Entra ID:

  • Quando possível, use a biblioteca MSAL e o suporte integrado para as repetições.
  • Se estiver a usar a API REST do Microsoft Entra ID, tente novamente a operação se o código de resultado for 429 (Muitos Pedidos) ou for um erro no intervalo 5xx. Não repita para nenhum outro erro.
  • Para erros 429, somente repita após o tempo indicado no cabeçalho Retry-After.
  • Para erros 5xx, use uma nova retirada exponencial, com a repetição pelo menos cinco segundos após a resposta.
  • Não repita em erros que não são 429 e 5xx.

Próximas etapas

Azure Cosmos DB

O Azure Cosmos DB é um banco de dados multimodelo totalmente gerenciado que dá suporte a dados JSON sem esquema. Ele oferece desempenho configurável e confiável, processamento transacional nativo JavaScript, além de ser criado para a nuvem com escala elástica.

Mecanismo de repetição

Os SDKs do Azure Cosmos DB tentam executar de novo automaticamente em determinadas condições de erro e os aplicativos de usuário são incentivados a ter as próprias políticas de repetição. Confira o guia para criar aplicativos resilientes com SDKs do Azure Cosmos DB para obter uma lista completa de condições de erro e quando tentar novamente.

Telemetria

Dependendo da linguagem do aplicativo, o diagnóstico e a telemetria são expostos como logs ou propriedades promovidas nas respostas da operação. Para obter mais informações, confira a seção "Capturar o diagnóstico" no SDK do Azure Cosmos DB para C# e no SDK do Azure Cosmos DB para Java.

Data Lake Store

O Data Lake Storage Gen2 torna o armazenamento do Azure a fundação para a criação de data lakes empresariais no Azure. O Data Lake Storage Gen2 permite que você gerencie facilmente grandes quantidades de dados.

A biblioteca de clientes do Data Lake de Arquivos do Armazenamento do Azure inclui todos os recursos necessários para que seja mais fácil para desenvolvedores, cientistas de dados e analistas armazenar dados de qualquer tamanho, forma ou velocidade, bem como realizar todo tipo de processamento e análise em diferentes plataformas e linguagens.

Mecanismo de repetição

O DataLakeServiceClient permite manipular recursos de serviço e sistemas de arquivos do Azure Data Lake. A conta de armazenamento fornece o namespace de nível superior para o serviço Data Lake. Ao criar o cliente, você pode fornecer as opções de configuração do cliente para se conectar ao serviço do Azure Data Lake (DataLakeClientOptions). O DataLakeClientOptions inclui uma propriedade Retry (herdada de Azure.Core.ClientOptions) que pode ser configurada (classe RetryOptions).

Telemetria

Monitorar o uso e o desempenho do Armazenamento do Azure é uma parte importante da operacionalização do serviço. Exemplos incluem operações frequentes, operações com alta latência ou operações que causam a limitação do lado do serviço.

Toda a telemetria para sua conta de armazenamento está disponível por meio de logs Armazenamento Azure no Azure Monitor. Esse recurso integra sua conta de armazenamento ao Log Analytics e aos Hubs de Eventos, além de permitir que você arquive logs em outra conta de armazenamento. Para ver a lista completa de logs de métricas e recursos e o esquema associado a eles, confira Referência de dados de monitoramento do Armazenamento do Azure.

Hubs de Eventos

Os Hubs de Eventos do Azure são um serviço de ingestão de telemetria de hiperescala que coleta, transforma e armazena milhões de eventos.

Mecanismo de repetição

O comportamento de repetição na biblioteca de cliente dos Hubs de Eventos do Azure é controlado pela propriedade RetryPolicy na classe EventHubClient. As tentativas de política padrão com retirada exponencial quando os Hubs de Eventos do Azure retornam um EventHubsException transitório ou um OperationCanceledException. A política de repetição padrão dos Hubs de Eventos é repetir até nove vezes com um tempo de retirada exponencial de até 30 segundos.

Exemplo

EventHubClient client = EventHubClient.CreateFromConnectionString("[event_hub_connection_string]");
client.RetryPolicy = RetryPolicy.Default;

Próximas etapas

Biblioteca de clientes da Hubs de Eventos do Azure para .NET

Hub IoT

O Hub IoT do Azure é um serviço para conectar, monitorar e gerenciar dispositivos para desenvolver aplicativos IoT (Internet das Coisas).

Mecanismo de repetição

O SDK do dispositivo IoT do Azure pode detectar erros na rede, protocolo ou aplicativo. Com base no tipo de erro, o SDK verifica se uma nova tentativa deve ser executada. Se o erro for recuperável, o SDK tentará novamente usando a política de repetição configurada.

A política de repetição padrão é uma retirada exponencial com variação aleatória, mas ela pode ser configurada.

Configuração de política

A configuração de política varia segundo o idioma. Para obter mais informações, consulte Configuração da política de repetição do Hub IoT.

Próximas etapas

Cache Redis do Azure

O Cache do Azure para Redis é um serviço de cache de baixa latência e acesso a dados rápido com base no popular cache de código aberto Redis. Ele é seguro, gerenciado pela Microsoft e pode ser acessado de qualquer aplicativo no Azure.

A diretriz nesta seção se baseia em como usar o cliente StackExchange.Redis para acessar o cache. Uma lista de outros clientes adequados pode ser encontrada no site do Redis, e eles podem ter mecanismos de repetição diferentes.

O cliente StackExchange.Redis usa multiplexação por meio de uma única conexão. O uso recomendado é criar uma instância do cliente na inicialização do aplicativo e usar essa instância para todas as operações no cache. Por esse motivo, a conexão com o cache é feita apenas uma vez, e toda a orientação desta seção está relacionada à política de repetição para esta conexão inicial, e não para cada operação que acessa o cache.

Mecanismo de repetição

O cliente StackExchange.Redis usa uma classe de gerenciador de conexões que é configurada por meio de um conjunto de opções, incluindo:

  • ConnectRetry. O número de vezes que uma conexão com falha para o cache será repetida.
  • ReconnectRetryPolicy. Usar qual estratégia de repetição.
  • ConnectTimeout. O tempo máximo de espera em milissegundos.

Configuração de política

As políticas de repetição são configuradas de modo programático, definindo as opções para o cliente antes de se conectar ao cache. Isso pode ser feito criando uma instância da classe ConfigurationOptions, populando suas propriedades e passando-a para o método Connect.

As classes internas suportam atraso linear (constante) e retirada exponencial com intervalos de repetição aleatórios. Você também pode criar uma política de repetição personalizada se implementar a interface IReconnectRetryPolicy.

O exemplo a seguir configura uma estratégia de repetição com retirada exponencial.

var deltaBackOffInMilliseconds = TimeSpan.FromSeconds(5).TotalMilliseconds;
var maxDeltaBackOffInMilliseconds = TimeSpan.FromSeconds(20).TotalMilliseconds;
var options = new ConfigurationOptions
{
    EndPoints = {"localhost"},
    ConnectRetry = 3,
    ReconnectRetryPolicy = new ExponentialRetry(deltaBackOffInMilliseconds, maxDeltaBackOffInMilliseconds),
    ConnectTimeout = 2000
};
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

Como alternativa, você pode especificar as opções como uma cadeia de caracteres e passá-la ao método Connect. A propriedade ReconnectRetryPolicy não pode ser definida dessa forma, somente por meio de código.

var options = "localhost,connectRetry=3,connectTimeout=2000";
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

Também é possível especificar opções diretamente ao se conectar ao cache.

var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,connectRetry=3");

Para obter mais informações, confira Configuração do Stack Exchange Redis na documentação do StackExchange.Redis.

A tabela a seguir mostra as configurações padrão da política de repetição interna.

Contexto Configuração Valor padrão
(v 1.2.2)
Significado
ConfigurationOptions ConnectRetry

ConnectTimeout

SyncTimeout

ReconnectRetryPolicy
3

Máximo de 5000 ms mais SyncTimeout
1000

LinearRetry 5.000 ms
O número de vezes para repetir tentativas de conexão durante a operação de conexão inicial.
Tempo limite (ms) para operações de conexão. Não é um intervalo entre tentativas de repetição.
Tempo (ms) para permitir operações síncronas.

Repita a cada 5.000 ms.

Observação

Em operações síncronas, SyncTimeout pode adicionar à latência de ponta a ponta, porém definir o valor muito baixo pode causar tempos limite excessivos. Veja Como solucionar problemas do Cache do Azure para Redis. Em geral, evite usar operações síncronas e use operações assíncronas. Para saber mais, confira Pipelines e multiplexadores.

Diretriz de uso de repetição

Considere as seguintes diretrizes ao usar o Cache do Azure para Redis:

  • O cliente StackExchange Redis gerencia suas próprias repetições, mas apenas ao estabelecer uma conexão com o cache quando o aplicativo é iniciado pela primeira vez. Você pode configurar o tempo limite da conexão, o número de repetições e o intervalo entre as repetições para estabelecer esta conexão, porém a política de repetições não se aplica a operações contra o cache.
  • Em vez de usar um grande número de tentativas de repetição, considere fazer fallback acessando a fonte de dados original.

Telemetria

Você pode coletar informações sobre conexões (mas não outras operações) usando um TextWriter.

var writer = new StringWriter();
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

Um exemplo da saída que isso gera é mostrado abaixo.

localhost:6379,connectTimeout=2000,connectRetry=3
1 unique nodes specified
Requesting tie-break from localhost:6379 > __Booksleeve_TieBreak...
Allowing endpoints 00:00:02 to respond...
localhost:6379 faulted: SocketFailure on PING
localhost:6379 failed to nominate (Faulted)
> UnableToResolvePhysicalConnection on GET
No masters detected
localhost:6379: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: Connecting; not in use: DidNotRespond
localhost:6379: int ops=0, qu=0, qs=0, qc=1, wr=0, sync=1, socks=2; sub ops=0, qu=0, qs=0, qc=0, wr=0, socks=2
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub: 0 (0.00 ops/s; spans 10s)
Sync timeouts: 0; fire and forget: 0; last heartbeat: -1s ago
resetting failing connections to retry...
retrying; attempts left: 2...
...

Exemplos

O exemplo de código a seguir configura um atraso constante (linear) entre as repetições ao inicializar o cliente StackExchange.Redis. Este exemplo mostra como definir a configuração usando uma instância de ConfigurationOptions.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace RetryCodeSamples
{
    class CacheRedisCodeSamples
    {
        public async static Task Samples()
        {
            var writer = new StringWriter();
            {
                try
                {
                    var retryTimeInMilliseconds = TimeSpan.FromSeconds(4).TotalMilliseconds; // delay between retries

                    // Using object-based configuration.
                    var options = new ConfigurationOptions
                                        {
                                            EndPoints = { "localhost" },
                                            ConnectRetry = 3,
                                            ReconnectRetryPolicy = new LinearRetry(retryTimeInMilliseconds)
                                        };
                    ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

                    // Store a reference to the multiplexer for use in the application.
                }
                catch
                {
                    Console.WriteLine(writer.ToString());
                    throw;
                }
            }
        }
    }
}

Este exemplo mostra como definir a configuração especificando as opções como uma cadeia de caracteres. O tempo limite da conexão é o período máximo de espera por uma conexão para o cache, não o atraso entre tentativas de repetição. A propriedade ReconnectRetryPolicy só pode ser definida por código.

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace RetryCodeSamples
{
    class CacheRedisCodeSamples
    {
        public async static Task Samples()
        {
            var writer = new StringWriter();
            {
                try
                {
                    // Using string-based configuration.
                    var options = "localhost,connectRetry=3,connectTimeout=2000";
                    ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

                    // Store a reference to the multiplexer for use in the application.
                }
                catch
                {
                    Console.WriteLine(writer.ToString());
                    throw;
                }
            }
        }
    }
}

Para obter mais exemplos, consulte Configuração no site do projeto.

Próximas etapas

O Azure Search pode ser usada para adicionar recursos potentes e sofisticados a um site ou aplicativo, ajustar os resultados da pesquisa de maneira rápida e fácil, bem como construir modelos de classificação avançados e ajustados.

Mecanismo de repetição

O SDK do Azure para .NET inclui uma biblioteca de clientes Azure.Search.Documents da equipe do SDK do Azure que é funcionalmente equivalente à biblioteca de clientes anterior, Microsoft.Azure.Search.

O comportamento de repetição no Microsoft.Azure.Search é controlado pelo método SetRetryPolicy nas classes SearchServiceClient e SearchIndexClient. A política padrão tenta novamente com retirada exponencial quando o Azure Search retorna uma resposta 5xx ou 408 (Tempo Limite da Solicitação).

O comportamento de repetição no Azure.Search.Documents é controlado por SearchClientOptions (ele faz parte do construtor SearchClient) na propriedade Retry, que pertence à classe Azure.Core.RetryOptions (em que todas as configurações estão disponíveis).

Telemetria

Rastreamento com o ETW ou por meio de registro de um provedor de rastreamento personalizado. Para obter mais informações, confira Documentação do AutoRest.

Barramento de Serviço

O Barramento de Serviço é uma plataforma de mensagens na nuvem que fornece troca de mensagens flexivelmente acoplada com escala e resiliência melhoradas para componentes de um aplicativo, se hospedado na nuvem ou no local.

Mecanismo de repetição

O namespace e alguns dos detalhes de configuração dependem de qual pacote de SDK de cliente do Barramento de Serviço é usado:

Pacote Descrição Namespace
Azure.Messaging.ServiceBus Biblioteca de clientes do Barramento de Serviço do Azure para .NET Azure.Messaging.ServiceBus
WindowsAzure.ServiceBus Este pacote é a antiga biblioteca de clientes do Barramento de Serviço. Ele requer o .NET Framework 4.5.2. Microsoft.Azure.ServiceBus

Diretriz de uso de repetição

A propriedade ServiceBusRetryOptions especifica as opções de repetição para o objeto ServiceBusClient:

Configuração Valor padrão Significado
CustomRetryPolicy Uma política de repetição personalizada a ser usada no lugar dos valores de opção individuais.
Atraso 0,8 segundos O atraso entre as tentativas de repetição, para uma abordagem fixa, ou o atraso no qual os cálculos serão baseados, para uma abordagem baseada em retirada.
MaxDelay 60 segundos O atraso máximo permitido entre as tentativas repetição.
MaxRetries 3 O número máximo de tentativas de repetição antes de considerar que a operação associada falhou.
Mode Exponencial A abordagem a ser usada para calcular atrasos de repetição.
TryTimeout 60 segundos A duração máxima para aguardar a conclusão de uma única tentativa, seja a tentativa inicial ou uma repetição.

Defina a propriedade Mode para configurar ServiceBusRetryMode com qualquer um desses valores:

Propriedade Valor Descrição
Exponencial 1 Novas tentativas irão causar um atraso baseado em uma estratégia de retirada, na qual cada tentativa aumentará a duração que ela aguarda antes de tentar novamente.
Fixo 0 Tentativas de repetição ocorrem em intervalos fixos; cada atraso é uma duração consistente.

Exemplo:

using Azure.Messaging.ServiceBus;

string connectionString = "<connection_string>";
string queueName = "<queue_name>";

// Because ServiceBusClient implements IAsyncDisposable, we'll create it
// with "await using" so that it is automatically disposed for us.
var options = new ServiceBusClientOptions();
options.RetryOptions = new ServiceBusRetryOptions
{
    Delay = TimeSpan.FromSeconds(10),
    MaxDelay = TimeSpan.FromSeconds(30),
    Mode = ServiceBusRetryMode.Exponential,
    MaxRetries = 3,
};
await using var client = new ServiceBusClient(connectionString, options);

Telemetria

O Barramento de Serviço coleta os mesmos tipos de dados de monitoramento que outros recursos do Azure. Você pode Monitorar o Barramento de Serviço do Azure usando o Azure Monitor.

Você também tem várias opções para enviar telemetria com as bibliotecas de clientes do .NET do Barramento de Serviço.

Exemplo

O código a seguir mostra como usar o pacote Azure.Messaging.ServiceBus para:

  • Defina a política de repetição para um ServiceBusClient usando um novo ServiceBusClientOptions.
  • Crie uma nova mensagem com uma nova instância de um ServiceBusMessage.
  • Enviar uma mensagem para o Barramento de Serviço usando o método ServiceBusSender.SendMessageAsync(message).
  • Receba usando o ServiceBusReceiver, que são representados como objetos ServiceBusReceivedMessage.
// using Azure.Messaging.ServiceBus;

using Azure.Messaging.ServiceBus;

string connectionString = "<connection_string>";
string queueName = "queue1";

// Because ServiceBusClient implements IAsyncDisposable, we'll create it 
// with "await using" so that it is automatically disposed for us.
var options = new ServiceBusClientOptions();
options.RetryOptions = new ServiceBusRetryOptions
{
    Delay = TimeSpan.FromSeconds(10),
    MaxDelay = TimeSpan.FromSeconds(30),
    Mode = ServiceBusRetryMode.Exponential,
    MaxRetries = 3,
};
await using var client = new ServiceBusClient(connectionString, options);

// The sender is responsible for publishing messages to the queue.
ServiceBusSender sender = client.CreateSender(queueName);
ServiceBusMessage message = new ServiceBusMessage("Hello world!");

await sender.SendMessageAsync(message);

// The receiver is responsible for reading messages from the queue.
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

string body = receivedMessage.Body.ToString();
Console.WriteLine(body);

Próximas etapas

Service Fabric

Distribuir serviços confiáveis em um cluster do Service Fabric protege contra a maioria das falhas transitórias potenciais discutidas neste artigo. No entanto, algumas falhas transitórias ainda podem acontecer. Por exemplo, se o serviço de nomeação recebe uma solicitação no meio de uma alteração de roteamento, ele pode lançar uma exceção. No entanto, se a mesma solicitação vier 100 milissegundos mais tarde, ela provavelmente terá êxito.

Internamente, o Service Fabric gerencia esse tipo de falha transitória. Você pode definir algumas configurações usando a classe OperationRetrySettings ao configurar seus serviços. O código a seguir mostra um exemplo. Na maioria dos casos, isso não deve ser necessário e as configurações padrão são suficientes.

FabricTransportRemotingSettings transportSettings = new FabricTransportRemotingSettings
{
    OperationTimeout = TimeSpan.FromSeconds(30)
};

var retrySettings = new OperationRetrySettings(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(1), 5);

var clientFactory = new FabricTransportServiceRemotingClientFactory(transportSettings);

var serviceProxyFactory = new ServiceProxyFactory((c) => clientFactory, retrySettings);

var client = serviceProxyFactory.CreateServiceProxy<ISomeService>(
    new Uri("fabric:/SomeApp/SomeStatefulReliableService"),
    new ServicePartitionKey(0));

Próximas etapas

Banco de Dados SQL usando o ADO.NET

O Banco de Dados SQL é um banco de dados SQL disponível em vários tamanhos e como um serviço padrão (compartilhado) e premium (não compartilhado).

Mecanismo de repetição

O Banco de Dados SQL não tem suporte interno para repetições quando acessado usando o ADO.NET. No entanto, os códigos de retorno das solicitações podem ser usados para determinar por que uma solicitação falhou. Para obter mais informações sobre a limitação do banco de dados SQL, confira Limites de recursos do banco de dados SQL do Azure. Para obter uma lista dos códigos de erro relevantes, confira códigos de erro SQL para aplicativos de cliente do banco de dados SQL.

Você pode usar a biblioteca Polly para implementar tentativas para o banco de dados SQL. Confira Falha transitória manipulando com a Polly.

Diretriz de uso de repetição

Considere as seguintes diretrizes ao acessar o Banco de Dados SQL usando o ADO.NET:

  • Escolha a opção de serviço apropriada (compartilhada ou premium). Uma instância compartilhada pode sofrer atrasos e limitação de conexão mais longos que o normal devido ao uso por outros locatários do servidor compartilhado. Se forem necessárias mais operações confiáveis de baixa latência e desempenho previsível, considere a escolha da opção premium.
  • Garanta a execução de repetições no nível ou escopo apropriado para evitar operações não idempotentes que causem inconsistência nos dados. De modo ideal, todas as operações devem ser idempotentes para que possam ser repetidas sem causar inconsistência. Quando não for esse o caso, a repetição deverá ser realizada em um nível ou escopo que permita que todas as alterações relacionadas sejam desfeitas, caso uma operação falhe; por exemplo, em um escopo transacional. Para saber mais, consulte Camada de acesso a dados dos conceitos básicos do serviço de nuvem — tratamento de falhas transitórias.
  • Uma estratégia de intervalo fixo não é recomendada para uso com o Banco de Dados SQL do Azure, exceto em cenários interativos em que há apenas algumas repetições em intervalos curtos. Em vez disso, considere usar uma estratégia de retirada exponencial para a maioria dos cenários.
  • Escolha um valor adequado para os tempos limite de conexão e comando ao definir conexões. Um tempo limite muito curto pode resultar em falhas prematuras de conexões quando o banco de dados estiver ocupado. Um tempo limite muito longo pode impedir que a lógica de repetição funcione corretamente, aguardando tempo demais para detectar uma conexão com falha. O valor do tempo limite é um componente da latência de ponta a ponta; ele é efetivamente adicionado ao intervalo de repetição especificado na política de repetição para cada tentativa de repetição.
  • Feche a conexão após algumas repetições, mesmo ao usar uma lógica de repetição de retirada exponencial, e repita a operação em uma nova conexão. Repetir a mesma operação várias vezes na mesma conexão pode ser um fator que contribui para problemas de conexão. Para obter um exemplo dessa técnica, consulte Camada de acesso a dados dos conceitos básicos do serviço de nuvem — tratamento de falhas transitórias.
  • Quando o pool de conexões está em uso (o padrão), é provável que a mesma conexão seja escolhida no pool, mesmo depois de fechar e reabrir uma conexão. Se for esse o caso, uma técnica para resolver isso é chamar o método ClearPool da classe SqlConnection para marcar a conexão como não reutilizável. No entanto, isso deve ser feito somente depois que várias tentativas de conexão tiverem falhado, e somente ao encontrar a classe específica de falhas transitórias, como tempos limite de SQL (código de erro -2), relacionada às conexões com falha.
  • Se o código de acesso a dados usar transações iniciadas como instâncias TransactionScope , a lógica de repetição deverá reabrir a conexão e iniciar um novo escopo de transação. Por esse motivo, o bloco de código com nova tentativa deve englobar o escopo inteiro da transação.

Considere começar com as seguintes configurações para operações de repetição. Essas configurações são de uso geral e você deve monitorar as operações e ajustar os valores para que se adequem ao seu cenário.

Contexto Exemplo de E2E de destino
latência máxima
Estratégia de repetição Configurações Valores Como funciona
Interativo, interface de usuário
ou primeiro plano
2 s FixedInterval Contagem de repetição
Intervalo de repetição
Primeira repetição rápida
3
500 ms
true
1ª tentativa — intervalo de 0 s
2ª tentativa — intervalo de 500 ms
3ª tentativa — intervalo de 500 ms
Tela de fundo
ou lote
30 s ExponentialBackoff Contagem de repetição
Retirada mín.
Retirada máx.
Retirada delta
Primeira repetição rápida
5
0 s
60 s
2 s
false
1ª tentativa — intervalo de 0 s
2ª tentativa — intervalo de ~2 s
3ª tentativa — intervalo de ~6 s
4ª tentativa — intervalo de ~14 s
5ª tentativa — intervalo de ~30 s

Observação

A latência de ponta a ponta visa o tempo limite padrão de conexões com o serviço. Se você especificar tempos limite de conexão mais longos, a latência de ponta a ponta será estendida por esse tempo adicional para cada tentativa de repetição.

Exemplos

Esta seção mostra como você pode usar a Polly para acessar o banco de dados SQL do Azure usando um conjunto de políticas de repetição configurado na classe Policy.

O código a seguir mostra um método de extensão na classe SqlCommand que chama ExecuteAsync com retirada exponencial.

public async static Task<SqlDataReader> ExecuteReaderWithRetryAsync(this SqlCommand command)
{
    GuardConnectionIsNotNull(command);

    var policy = Policy.Handle<Exception>().WaitAndRetryAsync(
        retryCount: 3, // Retry 3 times
        sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(200 * Math.Pow(2, attempt - 1)), // Exponential backoff based on an initial 200 ms delay.
        onRetry: (exception, attempt) =>
        {
            // Capture some information for logging/telemetry.
            logger.LogWarn($"ExecuteReaderWithRetryAsync: Retry {attempt} due to {exception}.");
        });

    // Retry the following call according to the policy.
    await policy.ExecuteAsync<SqlDataReader>(async token =>
    {
        // This code is executed within the Policy

        if (conn.State != System.Data.ConnectionState.Open) await conn.OpenAsync(token);
        return await command.ExecuteReaderAsync(System.Data.CommandBehavior.Default, token);

    }, cancellationToken);
}

Esse método de extensão assíncrono pode ser usado da seguinte maneira.

var sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = "[some query]";

using (var reader = await sqlCommand.ExecuteReaderWithRetryAsync())
{
    // Do something with the values
}

Próximas etapas

Banco de Dados SQL usando o Entity Framework 6

O Banco de Dados SQL é um banco de dados SQL disponível em vários tamanhos e como um serviço padrão (compartilhado) e premium (não compartilhado). O Entity Framework é um mapeador relacional de objeto que permite aos desenvolvedores do .NET trabalhar com dados relacionais usando objetos específicos de domínio. Com ele, não há a necessidade da maioria dos códigos de acesso a dados que os desenvolvedores geralmente precisam para escrever.

Mecanismo de repetição

O suporte à repetição é fornecido durante o acesso ao Banco de Dados SQL usando o Entity Framework 6.0 e versões posteriores por meio de um mecanismo chamado Lógica de Repetição/Resiliência de Conexão. Os principais recursos do mecanismo de repetição são:

  • A abstração primária é a interface IDbExecutionStrategy . Essa interface:
    • Define métodos Execute síncronos e assíncronos.
    • Define classes que podem ser usadas diretamente ou podem ser configuradas em um contexto de banco de dados como uma estratégia padrão, mapeadas para nome do provedor ou para um nome de provedor e nome de servidor. Quando configuradas em um contexto, as repetições ocorrem no nível de operações de banco de dados individuais, das quais pode haver várias de uma determinada operação de contexto.
    • Define quando repetir uma conexão com falha, e como.
  • Incluem várias implementações internas da interface IDbExecutionStrategy :
    • Padrão: sem repetição.
    • Padrão para Banco de Dados SQL (automático): sem repetição, mas inspeciona exceções e as encapsula com sugestão para usar a estratégia do Banco de Dados SQL.
    • Padrão para Banco de Dados SQL: exponencial (herdado da classe base) mais lógica de detecção do Banco de Dados SQL.
  • Implementam uma estratégia de retirada exponencial que inclui aleatoriedade.
  • As características das classes de repetição internas são com estado e sem thread-safe. No entanto, elas podem ser reutilizadas depois que a operação atual for concluída.
  • Se a contagem de repetição especificada for excedida, os resultados serão encapsulados em uma nova exceção. A exceção atual não é exibida.

Configuração de política

O suporte à repetição é fornecido durante o acesso ao Banco de Dados SQL usando o Entity Framework 6.0 e versões superiores. As políticas de repetição são configuradas de modo programático. A configuração não pode ser alterada por operação.

Ao configurar uma estratégia no contexto como o padrão, você especifica uma função que cria uma nova estratégia sob demanda. O código a seguir mostra como você pode criar uma classe de configuração de repetição que estende a classe base DbConfiguration .

public class BloggingContextConfiguration : DbConfiguration
{
  public BlogConfiguration()
  {
    // Set up the execution strategy for SQL Database (exponential) with 5 retries and 4 sec delay
    this.SetExecutionStrategy(
         "System.Data.SqlClient", () => new SqlAzureExecutionStrategy(5, TimeSpan.FromSeconds(4)));
  }
}

Depois isso pode ser especificado como a estratégia de repetição padrão para todas as operações usando o método SetConfiguration da instância DbConfiguration quando o aplicativo é iniciado. Por padrão, o EF vai descobrir e usar automaticamente a classe de configuração.

DbConfiguration.SetConfiguration(new BloggingContextConfiguration());

Você pode especificar a classe de configuração de repetição para um contexto anotando a classe de contexto com um atributo DbConfigurationType . No entanto, se você tiver apenas uma classe de configuração, o EF a usará sem a necessidade de anotar o contexto.

[DbConfigurationType(typeof(BloggingContextConfiguration))]
public class BloggingContext : DbContext

Se precisar usar estratégias de repetição diferentes para operações específicas ou desabilitar repetições para operações específicas, você poderá criar uma classe de configuração que permita suspender ou trocar estratégias, definindo um sinalizador no CallContext. A classe de configuração pode usar esse sinalizador para alternar estratégias ou desabilitar a estratégia fornecida por você e usar uma estratégia padrão. Para saber mais, confira Suspender a estratégia de execução (EF6 em diante).

Outra técnica para usar estratégias de repetição específicas para operações individuais é criar uma instância da classe de estratégia necessária e fornecer as configurações desejadas por meio de parâmetros. Você então chama o método ExecuteAsync .

var executionStrategy = new SqlAzureExecutionStrategy(5, TimeSpan.FromSeconds(4));
var blogs = await executionStrategy.ExecuteAsync(
    async () =>
    {
        using (var db = new BloggingContext("Blogs"))
        {
            // Acquire some values asynchronously and return them
        }
    },
    new CancellationToken()
);

A maneira mais simples de usar uma classe DbConfiguration é colocá-la no mesmo assembly da classe DbContext. No entanto, isso não é apropriado quando o mesmo contexto é necessário em cenários diferentes, como diferentes estratégias de repetição interativas e em segundo plano. Se os diferentes contextos forem executados em AppDomains separados, você poderá usar o suporte interno para especificar classes de configuração no arquivo de configuração ou defini-las explicitamente usando código. Se os diferentes contextos devem ser executados no mesmo AppDomain, será necessária uma solução personalizada.

Para saber mais, confira Configuração baseada em código (EF6 em diante).

A tabela a seguir mostra as configurações padrão para a política de repetição interna ao usar o EF6.

Configuração Valor padrão Significado
Política Exponencial Retirada exponencial.
MaxRetryCount 5 O número máximo de repetições.
MaxDelay 30 segundos O atraso máximo entre as repetições. Esse valor não afeta como a série de atrasos é computada. Ele apenas define um limite superior.
DefaultCoefficient 1 segundo O coeficiente para o cálculo de retirada exponencial. Esse valor não pode ser alterado.
DefaultRandomFactor 1,1 O multiplicador usado para adicionar um atraso aleatório a cada entrada. Esse valor não pode ser alterado.
DefaultExponentialBase 2 O multiplicador usado para calcular o próximo atraso. Esse valor não pode ser alterado.

Diretriz de uso de repetição

Considere as seguintes diretrizes ao acessar o Banco de Dados SQL usando o EF6:

  • Escolha a opção de serviço apropriada (compartilhada ou premium). Uma instância compartilhada pode sofrer atrasos e limitação de conexão mais longos que o normal devido ao uso por outros locatários do servidor compartilhado. Se forem necessárias operações confiáveis de baixa latência e desempenho previsível, considere a escolha da opção premium.

  • Uma estratégia de intervalo fixo não é recomendada para ser usada com o Banco de Dados SQL do Azure. Em vez disso, use uma estratégia de retirada exponencial, pois o serviço pode estar sobrecarregado e intervalos mais longos permitem mais tempo para a recuperação.

  • Escolha um valor adequado para os tempos limite de conexão e comando ao definir conexões. Baseie o tempo limite no seu design de lógica de negócios e por meio de teste. Talvez seja necessário modificar esse valor ao longo do tempo, uma vez que os volumes de dados ou os processos de negócios mudam. Um tempo limite muito curto pode resultar em falhas prematuras de conexões quando o banco de dados estiver ocupado. Um tempo limite muito longo pode impedir que a lógica de repetição funcione corretamente, aguardando tempo demais para detectar uma conexão com falha. O valor do tempo limite é um componente da latência de ponta a ponta, embora você não possa determinar facilmente quantos comandos serão executados ao salvar o contexto. Você pode alterar o tempo limite padrão definindo a propriedade CommandTimeout da instância DbContext.

  • O Entity Framework oferece suporte às configurações de repetição definidas em arquivos de configuração. No entanto, para máxima flexibilidade no Azure, você deve considerar a criação da configuração de modo programático dentro do aplicativo. Os parâmetros específicos das políticas de repetição, como o número de repetições e os intervalos da repetição, podem ser armazenados no arquivo de configuração de serviço e usados no runtime para criar as políticas apropriadas. Isso permite que as configurações sejam alteradas sem precisar reiniciar o aplicativo.

Considere começar com as seguintes configurações para operações de repetição. Você não pode especificar o intervalo entre tentativas de repetição (ele é fixo e gerado como uma sequência exponencial). Você pode especificar apenas os valores máximo, conforme mostrado aqui, a menos que você crie uma estratégia de repetição personalizada. Essas configurações são de uso geral e você deve monitorar as operações e ajustar os valores para que se adequem ao seu cenário.

Contexto Exemplo de E2E de destino
latência máxima
Política de repetição Configurações Valores Como funciona
Interativo, interface de usuário
ou primeiro plano
2 segundos Exponencial MaxRetryCount
MaxDelay
3
750 ms
1ª tentativa — intervalo de 0 s
2ª tentativa — intervalo de 750 ms
3ª tentativa — intervalo de 750 ms
Tela de fundo
ou lote
30 segundos Exponencial MaxRetryCount
MaxDelay
5
12 segundos
1ª tentativa — intervalo de 0 s
2ª tentativa — intervalo de ~1 s
3ª tentativa — intervalo de ~3 s
4ª tentativa — intervalo de ~7 s
5ª tentativa — intervalo de 12 s

Observação

A latência de ponta a ponta visa o tempo limite padrão de conexões com o serviço. Se você especificar tempos limite de conexão mais longos, a latência de ponta a ponta será estendida por esse tempo adicional para cada tentativa de repetição.

Exemplos

O exemplo de código a seguir define uma solução de acesso a dados simples que usa o Entity Framework. Ele estabelece uma estratégia de repetição específica definindo uma instância de uma classe chamada BlogConfiguration que estende DbConfiguration.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.SqlServer;
using System.Threading.Tasks;

namespace RetryCodeSamples
{
    public class BlogConfiguration : DbConfiguration
    {
        public BlogConfiguration()
        {
            // Set up the execution strategy for SQL Database (exponential) with 5 retries and 12 sec delay.
            // These values could be loaded from configuration rather than being hard-coded.
            this.SetExecutionStrategy(
                    "System.Data.SqlClient", () => new SqlAzureExecutionStrategy(5, TimeSpan.FromSeconds(12)));
        }
    }

    // Specify the configuration type if more than one has been defined.
    // [DbConfigurationType(typeof(BlogConfiguration))]
    public class BloggingContext : DbContext
    {
        // Definition of content goes here.
    }

    class EF6CodeSamples
    {
        public async static Task Samples()
        {
            // Execution strategy configured by DbConfiguration subclass, discovered automatically or
            // or explicitly indicated through configuration or with an attribute. Default is no retries.
            using (var db = new BloggingContext("Blogs"))
            {
                // Add, edit, delete blog items here, then:
                await db.SaveChangesAsync();
            }
        }
    }
}

Mais exemplos de como usar o mecanismo de repetição do Entity Framework podem ser encontrados em Lógica de resiliência/repetição de conexão.

Banco de Dados SQL usando o Entity Framework Core

O Entity Framework Core é um mapeador relacional de objeto que permite aos desenvolvedores do .NET Core trabalhar com dados usando objetos específicos de domínio. Com ele, não há a necessidade da maioria dos códigos de acesso a dados que os desenvolvedores geralmente precisam para escrever. Esta versão do Entity Framework foi criada a partir do zero e não herda todos os recursos do EF6.x automaticamente.

Mecanismo de repetição

O suporte à repetição é fornecido durante o acesso ao Banco de Dados SQL usando o Entity Framework Core por meio de um mecanismo chamado resiliência de conexão. A resiliência de conexão foi introduzida no EF Core 1.1.0.

A abstração primária é a interface IExecutionStrategy. A estratégia de execução para o SQL Server, incluindo o SQL Azure, está ciente dos tipos de exceção que podem ser repetidos e tem padrões específicos para o número máximo de tentativas, atrasos entre as repetições e assim por diante.

Exemplos

O código a seguir permite novas tentativas automáticas ao configurar o objeto DbContext, que representa uma sessão com o banco de dados.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFMiscellaneous.ConnectionResiliency;Trusted_Connection=True;",
            options => options.EnableRetryOnFailure());
}

O código a seguir mostra como executar uma transação com novas tentativas automáticas, usando uma estratégia de execução. A transação é definida em um representante. Se ocorrer uma falha transitória, a estratégia de execução invocará o representante novamente.

using (var db = new BloggingContext())
{
    var strategy = db.Database.CreateExecutionStrategy();

    strategy.Execute(() =>
    {
        using (var transaction = db.Database.BeginTransaction())
        {
            db.Blogs.Add(new Blog { Url = "https://blogs.msdn.com/dotnet" });
            db.SaveChanges();

            db.Blogs.Add(new Blog { Url = "https://blogs.msdn.com/visualstudio" });
            db.SaveChanges();

            transaction.Commit();
        }
    });
}

Armazenamento do Azure

Os serviços de Armazenamento do Azure incluem armazenamento de blobs, de tabelas, de arquivos e de filas de armazenamento.

Blobs, filas e arquivos

A classe ClientOptions é o tipo base para todos os tipos de opção de cliente e expõe várias opções de cliente comuns, como diagnóstico, repetição, transporte. Para fornecer as opções de configuração de cliente para se conectar ao Armazenamento de Arquivos, de Blobs, e de Filas do Azure, você deve usar o tipo derivado correspondente. No próximo exemplo, você usa a classe QueueClientOptions (derivada de ClientOptions) para configurar um cliente para se conectar ao serviço de Fila do Azure. A propriedade Retry é o conjunto de opções que podem ser especificadas para influenciar como as tentativas de repetição são feitas e como uma falha está qualificada para ser repetida.

using System;
using System.Threading;
using Azure.Core;
using Azure.Identity;
using Azure.Storage;
using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;

namespace RetryCodeSamples
{
    class AzureStorageCodeSamples {

        public async static Task Samples() {

               // Provide the client configuration options for connecting to Azure Queue Storage
                QueueClientOptions queueClientOptions = new QueueClientOptions()
                {
                    Retry = {
                    Delay = TimeSpan.FromSeconds(2),     //The delay between retry attempts for a fixed approach or the delay on which to base
                                                         //calculations for a backoff-based approach
                    MaxRetries = 5,                      //The maximum number of retry attempts before giving up
                    Mode = RetryMode.Exponential,        //The approach to use for calculating retry delays
                    MaxDelay = TimeSpan.FromSeconds(10)  //The maximum permissible delay between retry attempts
                    },

                    GeoRedundantSecondaryUri = new Uri("https://...")
                    // If the GeoRedundantSecondaryUri property is set, the secondary Uri will be used for GET or HEAD requests during retries.
                    // If the status of the response from the secondary Uri is a 404, then subsequent retries for the request will not use the
                    // secondary Uri again, as this indicates that the resource may not have propagated there yet.
                    // Otherwise, subsequent retries will alternate back and forth between primary and secondary Uri.
                };

                Uri queueServiceUri = new Uri("https://storageaccount.queue.core.windows.net/");
                string accountName = "Storage account name";
                string accountKey = "storage account key";

                // Create a client object for the Queue service, including QueueClientOptions.
                QueueServiceClient serviceClient = new QueueServiceClient(queueServiceUri, new DefaultAzureCredential(), queueClientOptions);

                CancellationTokenSource source = new CancellationTokenSource();
                CancellationToken cancellationToken = source.Token;

                // Return an async collection of queues in the storage account.
                var queues = serviceClient.GetQueuesAsync(QueueTraits.None, null, cancellationToken);

Suporte a tabelas

Observação

O Pacote Nuget do WindowsAzure.Storage e o Pacote Nuget Microsoft.Azure.Cosmos.Table foram preteridos. Para obter suporte à tabela do Azure, consulte pacote Nuget Azure.Data.Tables

Mecanismo de repetição

A biblioteca de clientes é baseada na biblioteca do Azure Core, que é uma biblioteca que fornece serviços abrangentes para outras bibliotecas de clientes.

Há muitos motivos pelos quais a falha pode ocorrer quando um aplicativo cliente tenta enviar uma solicitação de rede para um serviço. Alguns exemplos são tempo limite, falhas de infraestrutura de rede, serviço rejeitando a solicitação devido a limitação/disponibilidade, encerramento da instância de serviço devido à redução de serviço, a instância de serviço que será substituída por outra versão, falha de serviço devido a uma exceção sem tratamento etc. Oferecendo um mecanismo de repetição interno (com uma configuração padrão que o consumidor pode substituir), nossos SDKs e o aplicativo do consumidor tornam-se resilientes a esses tipos de falhas. Observe que alguns serviços cobram dinheiro real por cada solicitação e, portanto, os consumidores devem ser capazes de desabilitar totalmente as tentativas se preferirem economizar dinheiro em vez de resiliência.

Configuração de política

As políticas de repetição são configuradas de modo programático. A configuração é baseada na classe RetryOption. Há um atributo em TableClientOptions herdado de ClientOptions

      var tableClientOptions = new TableClientOptions();
      tableClientOptions.Retry.Mode = RetryMode.Exponential;
      tableClientOptions.Retry.MaxRetries = 5;
      var serviceClient = new TableServiceClient(connectionString, tableClientOptions);

As tabelas a seguir mostram as possibilidades para as políticas de repetição internas.

RetryOption

Configuração Significado
Atraso O atraso entre as tentativas de repetição, para uma abordagem fixa, ou o atraso no qual os cálculos serão baseados, para uma abordagem baseada em retirada. Se o serviço fornecer um cabeçalho de resposta Retry-After, a próxima repetição será atrasada pela duração especificada pelo valor do cabeçalho.
MaxDelay O atraso máximo permitido entre as tentativas de repetição quando o serviço não fornece um cabeçalho de resposta Retry-After. Se o serviço fornecer um cabeçalho de resposta Retry-After, a próxima repetição será atrasada pela duração especificada pelo valor do cabeçalho.
Mode A abordagem a ser usada para calcular atrasos de repetição.
NetworkTimeout O tempo limite aplicado a operações de rede individual.

RetryMode

Configuração Significado
Exponencial Novas tentativas irão causar um atraso baseado em uma estratégia de retirada, na qual cada tentativa aumentará a duração que ela aguarda antes de tentar novamente.
MaxDelay Tentativas de repetição ocorrem em intervalos fixos; cada atraso é uma duração consistente.

Telemetria

A maneira mais simples de ver os logs é habilitando o registro em log do console. Para criar um ouvinte de log do SDK do Azure que gera mensagens para o console, use o método AzureEventSourceListener.CreateConsoleLogger.

      // Setup a listener to monitor logged events.
      using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();

Exemplos

A execução do exemplo de código a seguir com o emulador de armazenamento desligado nos permitirá ver informações sobre novas tentativas no console.

using Azure.Core;
using Azure.Core.Diagnostics;
using Azure.Data.Tables;
using Azure.Data.Tables.Models;

namespace RetryCodeSamples
{
    class AzureStorageCodeSamples
    {
        private const string connectionString = "UseDevelopmentStorage=true";
        private const string tableName = "RetryTestTable";

        public async static Task SamplesAsync()
        {
            // Setup a listener to monitor logged events.
            using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();

            var tableClientOptions = new TableClientOptions();
            tableClientOptions.Retry.Mode = RetryMode.Exponential;
            tableClientOptions.Retry.MaxRetries = 5;

            var serviceClient = new TableServiceClient(connectionString, tableClientOptions);

            TableItem table = await serviceClient.CreateTableIfNotExistsAsync(tableName);
            Console.WriteLine($"The created table's name is {table.Name}.");
        }
    }
}

Diretrizes gerais de repetição e REST

Considere o seguinte ao acessar os serviços do Azure ou de terceiros:

  • Use uma abordagem sistemática para gerenciar repetições, talvez como código reutilizável, para que você possa aplicar uma metodologia consistente em todos os clientes e soluções.

  • Considere o uso de uma estrutura de repetição, como Polly, para gerenciar as repetições de tentativa se o cliente ou serviço de destino não tiver nenhum mecanismo de repetição interno. Isso ajudará você a implementar um comportamento de repetição consistente, bem como pode fornecer uma estratégia de repetição padrão adequada para o serviço de destino. No entanto, talvez seja necessário criar um código de repetição personalizado para serviços que tenham comportamento não padrão, que não dependem de exceções para indicar falhas transitórias ou, se desejar, use uma resposta Retry-Response para gerenciar o comportamento de repetição.

  • A lógica de detecção transitória dependerá da API de cliente real que você usa para invocar as chamadas REST. Alguns clientes, como a classe mais recente HttpClient, não lançam exceções para solicitações concluídas com um código de status HTTP sem sucesso.

  • O código de status HTTP retornado do serviço pode ajudar a indicar se a falha é transitória. Talvez seja necessário examinar as exceções geradas por um cliente ou pela estrutura de repetição para acessar o código de status ou determinar o tipo de exceção equivalente. Os seguintes códigos HTTP geralmente indicam que uma repetição é apropriada:

    • 408 Tempo Limite da Solicitação
    • 429 Excesso de Solicitações
    • Erro interno de servidor 500
    • 502 Gateway Incorreto
    • 503 Serviço Indisponível
    • 504 Tempo Limite do Gateway
  • Se você basear suas lógica de repetição em exceções, geralmente o que se segue indica uma falha transitória onde nenhuma conexão pode ser estabelecida:

    • WebExceptionStatus.ConnectionClosed
    • WebExceptionStatus.ConnectFailure
    • WebExceptionStatus.Timeout
    • WebExceptionStatus.RequestCanceled
  • No caso de um status de serviço indisponível, o serviço pode indicar o atraso apropriado antes de tentar a repetição no cabeçalho da resposta Retry-After ou em um cabeçalho personalizado diferente. Os serviços também podem enviar informações adicionais como cabeçalhos personalizados ou inseridos no conteúdo da resposta.

  • Não repita para os códigos de status que representam erros de cliente (erros no intervalo 4xx), exceto para 408 Tempo limite da solicitação esgotado e 429 Solicitações em excesso.

  • Teste minuciosamente seus mecanismos e estratégias de repetição sob diversas condições, como estado diferente de rede e cargas variáveis de sistema.

Estratégias de repetição

Veja a seguir os tipos comuns de intervalo de estratégias de repetição:

  • Exponencial. Uma política de repetição que executa um determinado número de repetições usando uma abordagem de retirada exponencial aleatória para determinar o intervalo entre as repetições. Por exemplo:

    var random = new Random();
    
    var delta = (int)((Math.Pow(2.0, currentRetryCount) - 1.0) *
                random.Next((int)(this.deltaBackoff.TotalMilliseconds * 0.8),
                (int)(this.deltaBackoff.TotalMilliseconds * 1.2)));
    var interval = (int)Math.Min(checked(this.minBackoff.TotalMilliseconds + delta),
                    this.maxBackoff.TotalMilliseconds);
    retryInterval = TimeSpan.FromMilliseconds(interval);
    
  • Incremental. Uma estratégia de repetição com um número especificado de tentativas de repetição e um intervalo de tempo incremental entre entradas. Por exemplo:

    retryInterval = TimeSpan.FromMilliseconds(this.initialInterval.TotalMilliseconds +
                    (this.increment.TotalMilliseconds * currentRetryCount));
    
  • LinearRetry. Uma política de repetição que executa um número especificado de repetições usando um intervalo de tempo fixo especificado entre as repetições. Por exemplo:

    retryInterval = this.deltaBackoff;
    

Falha transitória manipulada com a Polly

Polly é uma biblioteca para lidar programaticamente com repetições e estratégias de disjuntor. O projeto Polly é um membro da Fundação .NET. Para serviços em que o cliente não oferece suporte a novas tentativas, a Polly é uma alternativa válida e evita a necessidade de escrever código de repetição personalizado, que pode ser difícil de implementar corretamente. A Polly também fornece uma maneira de rastrear erros, para que você possa fazer novas tentativas.

Próximas etapas