Guía de reintentos para los servicios de Azure

La mayoría de SDK de cliente y de servicios de Azure incluye un mecanismo de reintento. Sin embargo, estos son diferentes porque cada servicio tiene requisitos y características diferentes, por lo que cada mecanismo de reintento se ajusta a un servicio específico. Esta guía resume las características de mecanismo de reintento de la mayoría de los servicios de Azure e incluye información para ayudarle a usar, adaptar o ampliar el mecanismo de reintento para ese servicio.

Para obtener instrucciones generales sobre el control de errores transitorios y reintentar conexiones y operaciones en servicios y recursos, consulte Guía de reintentos.

En la tabla siguiente se resumen las características de reintento de los servicios de Azure descritos en esta guía.

Servicio Capacidades de reintento Configuración de directivas Ámbito Características de telemetría
Microsoft Entra ID Nativo en la biblioteca MSAL Insertado en la biblioteca MSAL Interno None
Azure Cosmos DB Nativo en servicio No configurable Global TraceSource
Data Lake Store Nativo en el cliente No configurable Operaciones individuales None
Event Hubs Nativo en el cliente Programático Remoto None
IoT Hub Nativo en el SDK de cliente Programático Remoto None
Azure Cache for Redis Nativo en el cliente Programático Remoto TextWriter
Search Nativo en el cliente Programático Remoto ETW o personalizado
Service Bus Nativo en el cliente Programático Administrador de espacio de nombres, fábrica de mensajería y cliente ETW
Service Fabric Nativo en el cliente Programático Remoto None
SQL Database con ADO.NET Polly Declarativo y programático Instrucciones únicas o bloques de código Personalizado
SQL Database con Entity Framework Nativo en el cliente Programático Global por AppDomain None
SQL Database con Entity Framework Core Nativo en el cliente Programático Global por AppDomain None
Storage Nativo en el cliente Programático Operaciones de cliente e individuales TraceSource

Nota

Para la mayoría de los mecanismos de reintento integrados de Azure, actualmente no hay ninguna manera de aplicar una directiva de reintento diferente para distintos tipos de error o excepción. Debe configurar una directiva que proporcione un promedio de rendimiento y disponibilidad óptimo. Una forma de ajustar la directiva consiste en analizar archivos de registro para determinar el tipo de errores transitorios que se están produciendo.

Microsoft Entra ID

Microsoft Entra ID es una solución en la nube de administración de identidades y accesos integral que combina servicios de directorio fundamentales, gobernanza de identidades avanzada, seguridad y administración de acceso a aplicaciones. Microsoft Entra ID también ofrece a los desarrolladores una plataforma de administración de identidades para proporcionar control de acceso a sus aplicaciones, según las reglas y directivas centralizadas.

Nota:

Para obtener instrucciones de reintento en los puntos de conexión de Managed Service Identity, consulte Uso de una identidad de servicio administrada de máquina virtual de Azure para obtener tokens.

Mecanismo de reintento

Hay un mecanismo de reintento integrado para Microsoft Entra ID en la biblioteca de autenticación de Microsoft (MSAL). Para evitar bloqueos inesperados, se recomienda que las bibliotecas de terceros y el código de la aplicación no reintenten las conexiones con error y que dejen que MSAL controle los reintentos.

Instrucciones de uso del reintento

Tenga en cuenta las siguientes directrices cuando use Microsoft Entra ID:

  • Cuando sea posible, utilice la biblioteca MSAL y la compatibilidad para reintentos integrada.
  • Si va a usar la API de REST para Microsoft Entra ID, vuelva a intentar la operación si el código de resultado es 429 (Demasiadas solicitudes) o un error en el intervalo 5xx. No lo intente de nuevo para cualquier otro error.
  • En el caso de los errores 429, inténtelo de nuevo después de la hora indicada en el encabezado Retry-After.
  • En el caso de los errores 5xx, use el retroceso exponencial, con el primer reintento al menos 5 segundos después de la respuesta.
  • No vuelva a intentarlo en el caso de errores distintos de 429 y 5xx.

Pasos siguientes

Azure Cosmos DB

Azure Cosmos DB es una base de datos multimodelo completamente administrada que admite datos JSON sin esquema. Ofrece un rendimiento confiable y configurable, procesamiento transaccional de JavaScript nativo y se ha creado para la nube con la escala elástica.

Mecanismo de reintento

Los SDK de Azure Cosmos DB aplican el mecanismo de reintento automáticamente en determinadas condiciones de error. Se recomienda que las aplicaciones de usuario tengan sus propias directivas de reintento. Consulte la guía para diseñar aplicaciones resistentes con los SDK de Azure Cosmos DB para obtener una lista completa de las condiciones de error y cuándo aplicar el mecanismo de reintento.

Telemetría

En función del lenguaje de la aplicación, los diagnósticos y la telemetría se exponen como registros o propiedades promocionadas en las respuestas de la operación. Para obtener más información, consulte la sección "Capturar los diagnósticos" en el SDK de C# de Azure Cosmos DB y el SDK de Java de Azure Cosmos DB.

Data Lake Store

Data Lake Storage Gen2 convierte a Azure Storage en los cimientos para crear lagos de datos empresariales en Azure. Data Lake Storage Gen2 permite administrar fácilmente grandes cantidades de datos.

La Biblioteca cliente de Azure Storage Files Data Lake incluye todas las funcionalidades necesarias para facilitar a los desarrolladores, científicos de datos y analistas el almacenamiento de datos de cualquier tamaño, forma y velocidad, y realizar todos los tipos de procesamiento y análisis entre plataformas y lenguajes.

Mecanismo de reintento

DataLakeServiceClient permite manipular los recursos y sistemas de archivos del servicio de Azure Data Lake. La cuenta de almacenamiento proporciona el espacio de nombres de nivel superior para el servicio de Data Lake. Al crear el cliente, puedes proporcionar las opciones de configuración de cliente para conectarse al servicio de Azure Data Lake (DataLakeClientOptions). DataLakeClientOptions incluye una propiedad Retry (heredada de Azure.Core.ClientOptions) que se puede configurar (clase RetryOptions).

Telemetría

La supervisión del uso y el rendimiento de Azure Storage es una parte importante de la puesta en marcha del servicio. Algunos ejemplos son las operaciones frecuentes, las operaciones con latencia alta o las operaciones que provocan una limitación del servicio.

Toda la telemetría de la cuenta de almacenamiento está disponible a través de los registros de Azure Storage en Azure Monitor. Esta característica integra la cuenta de almacenamiento con Log Analytics y Event Hubs, al tiempo que permite archivar los registros en otra cuenta de almacenamiento. Para ver la lista completa de registros de métricas y recursos y su esquema asociado, consulte Referencia de datos de supervisión de Azure Storage.

Event Hubs

Azure Event Hubs es un servicio de ingesta de datos de telemetría a hiperescala que recopila, transforma y almacena millones de eventos.

Mecanismo de reintento

El comportamiento de reintentos de la biblioteca de cliente de Azure Event Hubs se controla mediante la propiedad RetryPolicy de la clase EventHubClient. La directiva predeterminada realiza reintentos con retroceso exponencial cuando Azure Event Hubs devuelve una excepción transitoria EventHubsException o OperationCanceledException. La directiva de reintentos predeterminada de Event Hubs admite hasta 9 reintentos con un tiempo de espera exponencial de hasta 30 segundos.

Ejemplo

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

Pasos siguientes

Biblioteca cliente de Azure Event Hubs para .NET

IoT Hub

Azure IoT Hub es un servicio para conectar, supervisar y administrar dispositivos para desarrollar aplicaciones de Internet de las cosas (IoT).

Mecanismo de reintento

El SDK de dispositivo IoT de Azure puede detectar errores de red, protocolo o aplicación. Según el tipo de error, el SDK de comprueba si debe realizarse un reintento. Si el error es recuperable, el SDK comienza a intentarlo de nuevo con la directiva de reintentos configurada.

La directiva de reintentos predeterminada es retroceso exponencial con distorsión aleatoria, pero se puede configurar.

Configuración de directivas

La configuración de las directivas difiere según el lenguaje. Para más información, consulte cómo configurar las directivas de reintentos de IoT Hub.

Pasos siguientes

Azure Cache for Redis

Azure Cache for Redis es un servicio de caché de acceso rápido a datos y de baja latencia basado en la conocida caché de Redis de código abierto. Es segura, está administrada por Microsoft y es accesible desde cualquier aplicación en Azure.

Las instrucciones de esta sección se basan en el uso del cliente StackExchange.Redis para tener acceso a la memoria caché. Puede encontrar una lista de otros clientes adecuados en el sitio web de Redis, y estos pueden tener mecanismos de reintento diferentes.

El cliente StackExchange.Redis usa multiplexación a través de una sola conexión. El uso recomendado es crear una instancia del cliente al iniciar la aplicación y usar esta instancia para todas las operaciones en la memoria caché. Por este motivo, la conexión a la memoria caché se realiza solo una vez y todas las instrucciones de esta sección están relacionadas con la directiva de reintentos de esta conexión inicial y no para cada operación que tiene acceso a la memoria caché.

Mecanismo de reintento

El cliente StackExchange.Redis usa una clase de administrador de conexiones que se configura mediante un conjunto de opciones, entre ellas:

  • ConnectRetry. Número de veces que se volverá a intentar una conexión con error a la memoria caché.
  • ReconnectRetryPolicy. Estrategia de reintentos que se usará.
  • ConnectTimeout. Tiempo de espera máximo en milisegundos.

Configuración de directivas

Las directivas de reintento se configuran mediante programación, estableciendo las opciones para el cliente antes de conectarse a la memoria caché. Esto puede hacerse mediante la creación de una instancia de la clase ConfigurationOptions, rellenando sus propiedades y pasándola al método Conectar.

Las clases integradas admiten retrasos lineales (constantes) y retroceso exponencial con intervalos de reintento aleatorios. También puede implementar la interfaz IReconnectRetryPolicy para crear una directiva de reintentos personalizada.

En el ejemplo siguiente se configura una estrategia de reintentos con retroceso 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, puede especificar las opciones como una cadena y pasar esto al método Conectar . Tenga en cuenta que la propiedad ReconnectRetryPolicy no se puede establecer de esta manera, sino solo mediante código.

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

También es posible especificar las opciones directamente al conectarse a la memoria caché.

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

Para más información, consulte Configuración de StackExchange.Redis en la documentación de StackExchange.Redis.

La siguiente tabla muestra la configuración predeterminada de la directiva de reintento integrada.

Contexto Configuración Valor predeterminado
(v 1.2.2)
Significado
ConfigurationOptions ConnectRetry

ConnectTimeout

SyncTimeout

ReconnectRetryPolicy
3

Máximo de 5000 ms más SyncTimeout
1000

LinearRetry 5000 ms
El número de veces que se repiten los intentos de conexión durante la operación de conexión inicial.
Tiempo de espera (ms) para conectar las operaciones. No un retraso entre reintentos.
Tiempo (ms) para permitir las operaciones sincrónicas.

Reintentar cada 5000 ms.

Nota

Para las operaciones sincrónicas, SyncTimeout puede agregar latencia de extremo a extremo, pero si se establece un valor demasiado bajo, puede provocar tiempos de espera excesivos. Consulte Solución de problemas de Azure Cache for Redis. Por lo general, evite el uso de las operaciones sincrónicas y use operaciones asincrónicas en su lugar. Para obtener más información, consulte Canalizaciones y multiplexores.

Instrucciones de uso del reintento

Tenga en cuenta las siguientes directrices cuando use Azure Cache for Redis:

  • El cliente Redis StackExchange administra sus propios reintentos, pero solo al establecer una conexión a la memoria caché cuando la aplicación se inicia por primera vez. Puede configurar el tiempo de espera de conexión, el número de reintentos y el tiempo entre reintentos para establecer esta conexión, pero la directiva de reintentos no se aplica a las operaciones en la memoria caché.
  • En lugar de usar un gran número de reintentos, considere la posibilidad de recurrir a obtener acceso a un origen de datos original en su lugar.

Telemetría

Puede recopilar información acerca de las conexiones (pero no otras operaciones) con un TextWriter.

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

A continuación, se muestra un ejemplo del resultado que este genera.

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...
...

Ejemplos

En el ejemplo de código siguiente se configura un retraso constante (lineal) entre los reintentos al inicializar el cliente StackExchange.Redis. Este ejemplo muestra cómo establecer la configuración mediante una instancia 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;
                }
            }
        }
    }
}

En este ejemplo se especifican las opciones como una cadena para establecer la configuración. El tiempo de espera de conexión es el período de tiempo máximo que se esperará a que se realice la conexión con la memoria caché; no es el retraso entre los reintentos. La propiedad ReconnectRetryPolicy solo puede establecerse mediante 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 obtener más ejemplos, consulte Configuración en el sitio web del proyecto.

Pasos siguientes

Azure Search puede usarse para agregar capacidades de búsqueda eficaces y sofisticadas a un sitio web o aplicación, ajustar de manera rápida y fácil los resultados de la búsqueda y construir modelos de clasificación enriquecidos y optimizados.

Mecanismo de reintento

Azure SDK para .NET incluye una biblioteca cliente Azure.Search.Documents del equipo de Azure SDK que es funcionalmente equivalente a la biblioteca cliente anterior, Microsoft.Azure.Search.

El comportamiento de reintento en Microsoft.Azure.Search se controla mediante el método SetRetryPolicy en las clases SearchServiceClient y SearchIndexClient. Los reintentos de directiva predeterminada con interrupción exponencial cuando Azure Search devuelve una respuesta 5xx o 408 (tiempo de espera de solicitud).

El comportamiento de reintento en Azure.Search.Documents se controla mediante SearchClientOptions (forma parte del constructor SearchClient) de la propiedad Retry, que pertenece a la clase Azure.Core.RetryOptions(donde todas las configuraciones están disponibles).

Telemetría

Realice un seguimiento con ETW o mediante el registro de un proveedor de seguimiento personalizado. Para más información, consulte la documentación de AutoRest.

Azure Service Bus

Service Bus es una plataforma de mensajería de nube que proporciona el intercambio de mensajes de acoplamiento flexible con mejor escala y resistencia para los componentes de una aplicación, ya esté hospedada en la nube o localmente.

Mecanismo de reintento

El espacio de nombres y algunos de los detalles de configuración dependen del paquete SDK cliente de Service Bus que se usa:

Paquete Descripción Espacio de nombres
Azure.Messaging.ServiceBus Biblioteca cliente de Azure Service Bus para .NET Azure.Messaging.ServiceBus
WindowsAzure.ServiceBus Este paquete es la antigua biblioteca cliente de Service Bus. Requiere .NET Framework 4.5.2. Microsoft.Azure.ServiceBus

Instrucciones de uso del reintento

La propiedad ServiceBusRetryOptions especifica las opciones de reintento para el objeto ServiceBusClient:

Configuración Valor predeterminado Significado
CustomRetryPolicy Una directiva de reintentos personalizada que se usará en lugar de los valores de opción individuales.
Delay 0.8 segundos El retraso entre los reintentos de un enfoque fijo o el retraso en el que se basan los cálculos de un enfoque basado en retroceso.
MaxDelay 60 segundos Retraso máximo permisible entre los reintentos.
MaxRetries 3 Número máximo de reintentos antes de considerar que hay un error en la operación asociada.
Modo Exponencial Enfoque que se debe usar para calcular los retrasos de reintento.
TryTimeout 60 segundos La duración máxima para esperar la finalización de un único intento, ya sea el intento inicial o un reintento.

Establezca la propiedad Mode para configurar ServiceBusRetryMode con cualquiera de estos valores:

Propiedad Valor Descripción
Exponencial 1 Habrá un retraso en los reintentos en función de una estrategia de interrupción, en la que cada intento aumentará la duración que espera antes de volver a intentarlo.
Corregido 0 Los reintentos se producen a intervalos fijos; cada retraso es una duración coherente.

Ejemplo:

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);

Telemetría

Service Bus recopila los mismos tipos de datos de supervisión que otros recursos de Azure. Puede supervisar Azure Service Bus mediante Azure Monitor.

También tiene varias opciones para enviar telemetría con las bibliotecas cliente de .NET de Service Bus.

Ejemplo

En el ejemplo de código siguiente se muestra cómo se utiliza el paquete Azure.Messaging.ServiceBus para:

  • Establecer la directiva de reintentos para ServiceBusClient mediante un nuevo ServiceBusClientOptions.
  • Crear un mensaje con una nueva instancia de ServiceBusMessage.
  • Envíe un mensaje a Service Bus mediante el método ServiceBusSender.SendMessageAsync(message).
  • Recibir mediante el ServiceBusReceiver, que se representan 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);

Pasos siguientes

Service Fabric

Distribuir servicios confiables en un clúster de Service Fabric protege frente a la mayoría de los errores transitorios posibles descritos en este artículo. Sin embargo, aún se pueden producir algunos errores transitorios. Por ejemplo, el servicio de nombres podría estar en medio de un cambio de enrutamiento cuando recibe una solicitud, lo que hace que se produzca una excepción. Si la misma solicitud llega 100 milisegundos después, probablemente se realizará correctamente.

Internamente, Service Fabric administra este tipo de errores transitorios. Puede configurar algunas opciones mediante la clase OperationRetrySettings al configurar los servicios. El código siguiente muestra un ejemplo. En la mayoría de los casos, esto no será necesario y la configuración predeterminada funcionará bien.

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));

Pasos siguientes

SQL Database mediante ADO.NET

SQL Database es una instancia de SQL Database hospedada que está disponible en una amplia variedad de tamaños y como un servicio estándar (compartido) y premium (no compartido).

Mecanismo de reintento

SQL Database no tiene soporte integrado para reintentos cuando se tiene acceso mediante ADO.NET. Sin embargo, los códigos de retorno de solicitudes pueden usarse para determinar el motivo del error de una solicitud. Para más información acerca de la limitación de SQL Database, consulte Límites de recursos de Azure SQL Database. Para obtener una lista de los códigos de error pertinentes, consulte Códigos de error SQL para las aplicaciones de cliente de SQL Database.

Puede usar la biblioteca de Polly implementar reintentos para SQL Database. Consulte Control de errores transitorios con Polly.

Instrucciones de uso del reintento

Al obtener acceso a la SQL Database mediante ADO.NET, tenga en cuenta las siguientes directrices:

  • Elija la opción de servicio adecuada (compartida o premium). Una instancia compartida puede sufrir retrasos en la conexión más largos de lo habitual y limitaciones debido al uso de otros inquilinos del servidor compartido. Si se requieren más operaciones de rendimiento predecible y de latencia baja confiable, considere la posibilidad de elegir la opción premium.
  • Asegúrese de realizar reintentos al nivel o ámbito adecuado para evitar las operaciones no idempotentes que provocan incoherencias en los datos. Lo ideal es que todas las operaciones sean idempotentes para que puedan repetirse sin causar incoherencias. Si no es el caso, el reintento deberá realizarse en un nivel o ámbito que permita que todos los cambios relacionados se deshagan si se produce un error en una operación; por ejemplo, desde dentro de un ámbito transaccional. Para obtener más información, consulte Capa de acceso a datos de fundamentos del servicio de nube: tratamiento de errores transitorios.
  • No se recomienda una estrategia de intervalo fijo para su uso con Azure SQL Database excepto para los escenarios interactivos donde hay solo unos cuantos reintentos a intervalos cortos. En su lugar, considere el uso de una estrategia de retroceso exponencial para la mayoría de escenarios.
  • Elija un valor adecuado para los tiempos de espera de conexión y comando a la hora de definir las conexiones. Un tiempo de espera demasiado corto puede provocar errores prematuros en las conexiones cuando la base de datos está ocupada. Un tiempo de espera demasiado largo puede impedir que la lógica de reintento funcione correctamente esperando demasiado tiempo antes de detectar un error en la conexión. El valor de tiempo de espera es un componente de la latencia de un extremo a otro; se agrega eficazmente al intervalo entre reintentos especificado en la directiva de reintentos para cada reintento.
  • Cierre la conexión después de algunos reintentos, incluso cuando se usa una lógica de reintentos de interrupción exponencial y vuelva a intentar la operación en una conexión nueva. Reintentar la misma operación varias veces en la misma conexión puede ser un factor que contribuya a ocasionar problemas de conexión. Para obtener un ejemplo de esta técnica, consulte Capa de acceso a datos de fundamentos del servicio de nube: tratamiento de errores transitorios.
  • Cuando el grupo de conexiones está en uso (valor predeterminado) es probable que se elija la misma conexión del grupo, incluso después de cerrar y volver a abrir una conexión. Si este es el caso, una técnica para resolverlo es llamar al método ClearPool de la clase SqlConnection para marcar la conexión como no reutilizable. Sin embargo, debería hacerlo solo después de que fallen varios intentos de conexión y solo al encontrar la clase específica de errores transitorios como tiempos de espera SQL (código de error -2) relacionados con conexiones erróneas.
  • Si el código de acceso de datos usa las transacciones iniciadas como instancias TransactionScope , la lógica de reintento debe volver a abrir la conexión e iniciar un nuevo ámbito de transacción. Por este motivo, el bloque de código que se puede reintentar debe abarcar todo el ámbito de la transacción.

Considere la posibilidad de comenzar con la configuración siguiente para las operaciones de reintento. Esta configuración es de uso general, y debe supervisar las operaciones y ajustar los valores para adaptarlos a su propio escenario.

Contexto E2E de destino de ejemplo
latencia máxima
Estrategia de reintento Configuración Valores Funcionamiento
Interactivo, interfaz de usuario
o primer plano
2 segundos FixedInterval Número de reintentos
Intervalo de reintento
Primer reintento rápido
3
500 ms
true
Intento 1 - retraso de 0 segundos
Intento 2 - retraso de 500 ms
Intento 3 – retraso de 500 ms
Información previa
o proceso por lotes
30 segundos ExponentialBackoff Número de reintentos
Interrupción mínima
Interrupción máxima
Interrupción delta
Primer reintento rápido
5
0 segundos
60 segundos
2 segundos
false
Intento 1 - retraso de 0 segundos
Intento 2 - retraso de ~2 segundos
Intento 3 - retraso de ~6 segundos
Intento 4 - retraso de ~14 segundos
Intento 5 - retraso de ~30 segundos

Nota

Los destinos de latencia de extremo a extremo suponen el tiempo de espera predeterminado para las conexiones con el servicio. Si especifica tiempos de espera de conexión más largos, la latencia de extremo a extremo se extenderá este tiempo adicional en cada reintento.

Ejemplos

En esta sección se muestra cómo usar Polly para acceder a Azure SQL Database mediante un conjunto de directivas de reintento configurado en la clase Policy.

El código siguiente muestra un método de extensión en la clase SqlCommand que llama a ExecuteAsync con retroceso 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);
}

Este método de extensión asincrónico puede utilizarse como se indica a continuación.

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

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

Pasos siguientes

SQL Database mediante Entity Framework 6

SQL Database es una instancia de SQL Database hospedada que está disponible en una amplia variedad de tamaños y como un servicio estándar (compartido) y premium (no compartido). Entity Framework es un mapeador relacional de objetos que permite a los desarrolladores de .NET trabajar con datos relacionales usando objetos específicos del dominio. Elimina la necesidad de usar la mayoría del código de acceso a datos que los programadores suelen tener que escribir.

Mecanismo de reintento

Se proporciona compatibilidad con los reintentos al obtener acceso a la instancia de SQL Database mediante Entity Framework 6.0 y versiones posteriores mediante un mecanismo denominado resistencia de la conexión y lógica de reintento. Las características principales del mecanismo de reintento son:

  • La abstracción principal es la interfaz IDbExecutionStrategy . Esta interfaz:
    • Define métodos Execute sincrónicos y asincrónicos.
    • Define las clases que pueden usarse o configurarse directamente en un contexto de base de datos como una estrategia predeterminada, asignada al nombre de un proveedor o asignada a un nombre de proveedor y de servidor. Cuando se configura en un contexto, los reintentos se producen en el nivel de operaciones de base de datos individual, de las que podría haber varias para una operación de contexto especificada.
    • Define cuándo se debe reintentar una conexión fallida y cómo.
  • Incluye varias implementaciones integradas de la interfaz IDbExecutionStrategy :
    • Predeterminado: ningún reintento.
    • Valor predeterminado para SQL Database (automático): sin reintento, pero inspecciona las excepciones y las ajusta con la recomendación de usar la estrategia de SQL Database.
    • Predeterminado para SQL Database: exponencial (heredado de la clase base) más la lógica de detección de SQL Database.
  • Implementa una estrategia de retroceso exponencial que incluye la selección aleatoria.
  • Las clases de reintento integradas son con estado y no son seguras para subprocesos. Sin embargo, se pueden volver a usar una vez completada la operación actual.
  • Si se supera el número de reintentos especificado, los resultados se encapsulan en una nueva excepción. No se propaga la excepción actual.

Configuración de directivas

Al obtener acceso a SQL Database mediante Entity Framework 6.0 y versiones posteriores, se proporciona compatibilidad con los reintentos. Las directivas de reintento se configuran mediante programación. No se puede cambiar la configuración en cada operación.

Al configurar una estrategia en el contexto como valor predeterminado, especifique una función que cree una nueva estrategia a petición. El código siguiente muestra cómo puede crear una clase de configuración de reintento que amplíe la clase 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)));
  }
}

A continuación, puede especificar esto como estrategia de reintento predeterminada para todas las operaciones mediante el método SetConfiguration de la instancia DbConfiguration cuando se inicia la aplicación. De forma predeterminada, EF detectará y usará automáticamente la clase de configuración.

DbConfiguration.SetConfiguration(new BloggingContextConfiguration());

Puede especificar la clase de configuración de reintento para un contexto anotando la clase de contexto con un atributo DbConfigurationType . Sin embargo, si solo tiene una clase de configuración, EF la usará sin necesidad de anotar el contexto.

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

Si necesita usar estrategias de reintento diferentes para operaciones específicas o deshabilitar reintentos para operaciones específicas, puede crear una clase de configuración que permita suspender o intercambiar estrategias estableciendo un indicador en CallContext. La clase de configuración puede usar este indicador para cambiar las estrategias o deshabilitar la estrategia proporcionada por usted y usar una estrategia predeterminada. Para más información, vea Suspenda la estrategia de ejecución (EF6 y versiones posteriores).

Otra técnica para el uso de estrategias de reintento específica para las operaciones individuales es crear una instancia de la clase de estrategia necesaria y proporcionar la configuración deseada a través de parámetros. A continuación, invoque su 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()
);

La manera más sencilla de usar una clase DbConfiguration es buscarla en el mismo ensamblado que la clase DbContext. Sin embargo, esto no es adecuado cuando se requiere el mismo contexto en diferentes escenarios, como diferentes estrategias de reintento interactivo y en segundo plano. Si los contextos diferentes se ejecutan en dominios de aplicación independientes, puede usar la compatibilidad integrada para especificar clases de configuración en el archivo de configuración o establecerla explícitamente mediante código. Si se deben ejecutar los contextos diferentes en el mismo dominio de aplicación, se requerirá una solución personalizada.

Para más información, vea Configuración basada en código (EF6 y versiones posteriores).

La siguiente tabla muestra la configuración predeterminada de las directivas de reintento integradas cuando se usa EF6.

Configuración Valor predeterminado Significado
Directiva Exponencial Retroceso exponencial.
MaxRetryCount 5 El número máximo de reintentos.
MaxDelay 30 segundos El retraso máximo entre los reintentos. Este valor no afecta al modo en que se calcula la serie de retrasos. Solo define un límite superior.
DefaultCoefficient 1 segundo El coeficiente para el cálculo del retroceso exponencial. Este valor no se puede cambiar.
DefaultRandomFactor 1.1 El multiplicador utilizado para agregar un retraso aleatorio para cada entrada. Este valor no se puede cambiar.
DefaultExponentialBase 2 El multiplicador utilizado para calcular el retraso siguiente. Este valor no se puede cambiar.

Instrucciones de uso del reintento

Al obtener acceso a la SQL Database mediante EF6, tenga en cuenta las siguientes directrices:

  • Elija la opción de servicio adecuada (compartida o premium). Una instancia compartida puede sufrir retrasos en la conexión más largos de lo habitual y limitaciones debido al uso de otros inquilinos del servidor compartido. Si se requieren un rendimiento predecible y operaciones de latencia baja confiable, considere la posibilidad de elegir la opción premium.

  • No se recomienda una estrategia de intervalo fijo para su uso con Azure SQL Database. En su lugar, use una estrategia de retroceso exponencial debido a que el servicio esté sobrecargado, y retrasos más prolongados permiten un mayor tiempo para la recuperación.

  • Elija un valor adecuado para los tiempos de espera de conexión y comando a la hora de definir las conexiones. Base el tiempo de espera en el diseño de la lógica de negocios y a través de pruebas. Puede que necesite modificar este valor con el tiempo a medida que los volúmenes de datos o los procesos empresariales cambien. Un tiempo de espera demasiado corto puede provocar errores prematuros en las conexiones cuando la base de datos está ocupada. Un tiempo de espera demasiado largo puede impedir que la lógica de reintento funcione correctamente esperando demasiado tiempo antes de detectar un error en la conexión. El valor de tiempo de espera es un componente de la latencia de un extremo a otro, aunque no podrá determinar fácilmente cuántos comandos se ejecutarán cuando se guarde el contexto. Puede cambiar el tiempo de espera predeterminado estableciendo la propiedad CommandTimeout de la instancia DbContext.

  • Entity Framework admite configuraciones de reintento definidas en archivos de configuración. Sin embargo, para obtener la máxima flexibilidad en Azure puede crear la configuración mediante programación dentro de la aplicación. Los parámetros específicos para las directivas de reintento, como el número de reintentos y los intervalos de reintento, se pueden almacenar en el archivo de configuración del servicio y usar en tiempo de ejecución para crear las directivas apropiadas. Esto permite cambiar la configuración sin necesidad de que la aplicación se reinicie.

Considere la posibilidad de comenzar con la configuración siguiente para las operaciones de reintento. No se puede especificar el retraso entre reintentos (es fijo y se genera como una secuencia exponencial). Puede especificar solo los valores máximos, como se muestra aquí, a menos que cree una estrategia de reintento personalizada. Esta configuración es de uso general, y debe supervisar las operaciones y ajustar los valores para adaptarlos a su propio escenario.

Contexto E2E de destino de ejemplo
latencia máxima
Directiva de reintentos Configuración Valores Funcionamiento
Interactivo, interfaz de usuario
o primer plano
2 segundos Exponencial MaxRetryCount
MaxDelay
3
750 ms
Intento 1 - retraso de 0 segundos
Intento 2 - retraso de 750 ms
Intento 3 – retraso de 750 ms
Información previa
o proceso por lotes
30 segundos Exponencial MaxRetryCount
MaxDelay
5
12 segundos
Intento 1 - retraso de 0 segundos
Intento 2 - retraso de ~1 segundos
Intento 3 - retraso de ~3 segundos
Intento 4 - retraso de ~7 segundos
Intento 5 - retraso de 12 segundos

Nota

Los destinos de latencia de extremo a extremo suponen el tiempo de espera predeterminado para las conexiones con el servicio. Si especifica tiempos de espera de conexión más largos, la latencia de extremo a extremo se extenderá este tiempo adicional en cada reintento.

Ejemplos

En el ejemplo de código siguiente se define una solución de acceso de datos simple que utiliza Entity Framework. Establece una estrategia de reintento específica mediante la definición de una instancia de una clase denominada BlogConfiguration que extiende 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();
            }
        }
    }
}

Más ejemplos de uso del mecanismo de reintento de Entity Framework se pueden encontrar en Resistencia de la conexión/lógica de reintento.

SQL Database mediante Entity Framework Core

Entity Framework Core es un mapeador relacional de objetos que permite a los desarrolladores de .NET trabajar con datos usando objetos específicos del dominio. Elimina la necesidad de usar la mayoría del código de acceso a datos que los programadores suelen tener que escribir. Esta versión de Entity Framework se escribió desde el principio y no hereda automáticamente todas las características de EF6.x.

Mecanismo de reintento

La compatibilidad con los reintentos se proporciona al obtener acceso a SQL Database mediante Entity Framework Core mediante un mecanismo denominado resistencia de la conexión. La resistencia de la conexión se incorporó por primera vez en EF Core 1.1.0.

La abstracción principal es la interfaz IExecutionStrategy. La estrategia de ejecución para SQL Server, incluido SQL Azure, conoce los tipos de excepción que se pueden recuperar y tiene valores predeterminados razonables para el número máximo de reintentos o el retraso entre los reintentos, entre otros.

Ejemplos

El código siguiente permite reintentos automáticos cuando se configura el objeto DbContext, que representa una sesión con la base de datos.

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

El código siguiente muestra cómo ejecutar una transacción con reintentos automáticos, mediante el uso de una estrategia de ejecución. La transacción se define en un delegado. Si se produce un error transitorio, la estrategia de ejecución invoca al delegado de nuevo.

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();
        }
    });
}

Azure Storage

Los servicios de Azure Storage incluyen almacenamiento de blobs, archivos y colas de almacenamiento.

Blobs, colas y archivos

La clase ClientOptions es el tipo base para todos los tipos de opciones de cliente y expone diversas opciones de cliente comunes como Diagnósticos, Reintentos y Transporte. Para proporcionar las opciones de configuración de cliente para conectarse a Cola de Azure, Blob y File Storage debe usar el tipo derivado correspondiente. En el siguiente ejemplo, se usa la clase QueueClientOptions (derivada de ClientOptions) para configurar un cliente para que se conecte al servicio Cola de Azure. La propiedad Retry es el conjunto de opciones que se pueden especificar para influir en el modo en que se realizan los intentos de reintento y en cómo se puede volver a intentar un error.

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);

Compatibilidad con tablas

Nota

El paquete Nuget de WindowsAzure.Storage y el paquete Nuget de Microsoft.Azure.Cosmos.Table han quedado en desuso. Para obtener compatibilidad con tablas de Azure, consulte Paquete NuGet de Azure.Data.Tables

Mecanismo de reintento

La biblioteca cliente se basa en la biblioteca de Azure Core, que es una biblioteca que proporciona servicios transversales a otras bibliotecas cliente.

Hay muchas razones por las que se puede producir un error cuando una aplicación cliente intenta enviar una solicitud de red a un servicio. Algunos ejemplos son el tiempo de espera, los errores de infraestructura de red, el servicio que rechaza la solicitud debido a limitaciones o disponibilidad, la finalización de la instancia de servicio debido a la reducción vertical del servicio, la instancia de servicio que se va a reemplazar por otra versión, el bloqueo del servicio debido a una excepción no controlada, etc. Al ofrecer un mecanismo de reintento integrado (con una configuración predeterminada que el consumidor puede invalidar), nuestros SDK y la aplicación del consumidor se vuelven resistentes a estos tipos de errores. Hay que tener en cuenta que algunos servicios cobran dinero real por cada solicitud, por lo que los consumidores deberían poder desactivar por completo los reintentos si prefieren ahorrar dinero a la resistencia.

Configuración de directivas

Las directivas de reintento se configuran mediante programación. La configuración se basa en la clase RetryOption. Hay un atributo en TableClientOptions heredado de ClientOptions

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

La siguiente tabla muestra las posibilidades de las directivas de reintento integradas.

RetryOption

Configuración Significado
Delay El retraso entre los reintentos de un enfoque fijo o el retraso en el que se basan los cálculos de un enfoque basado en retroceso. Si el servicio proporciona un encabezado de respuesta Retry-After, el reintento siguiente se retrasará durante el tiempo especificado por el valor del encabezado.
MaxDelay Retraso máximo permitido entre reintentos cuando el servicio no proporciona un encabezado de respuesta Retry-After. Si el servicio proporciona un encabezado de respuesta Retry-After, el reintento siguiente se retrasará durante el tiempo especificado por el valor del encabezado.
Mode Enfoque que se debe usar para calcular los retrasos de reintento.
NetworkTimeout Tiempo de espera que se aplica a una operación de red individual.

RetryMode

Configuración Significado
Exponencial Habrá un retraso en los reintentos en función de una estrategia de interrupción, en la que cada intento aumentará la duración que espera antes de volver a intentarlo.
MaxDelay Los reintentos se producen a intervalos fijos; cada retraso es una duración coherente.

Telemetría

La manera más sencilla de ver los registros es habilitar el registro de la consola. Para crear un agente de escucha de registro del SDK de Azure que genere mensajes en la consola, use el método AzureEventSourceListener.CreateConsoleLogger.

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

Ejemplos

La ejecución del ejemplo de código siguiente con el emulador de almacenamiento apagado nos permitirá ver información sobre los reintentos en la consola.

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}.");
        }
    }
}

Directrices generales de REST y de reintento

Al obtener acceso a los servicios de Azure o de terceros, tenga en cuenta lo siguiente:

  • Use un enfoque sistemático para administrar reintentos, quizás como código reutilizable, para que pueda aplicar una metodología coherente en todos los clientes y todas las soluciones.

  • Considere la posibilidad de usar un marco de reintentos, como Polly, para administrar los reintentos si el servicio de destino o el cliente no tienen ningún mecanismo de reintentos integrado. Esto le ayudará a implementar un comportamiento de reintento coherente y puede proporcionar una estrategia de reintento predeterminada adecuados para el servicio de destino. Sin embargo, puede que necesite crear código de reintento personalizado para los servicios que tienen un comportamiento no estándar, que no dependen de excepciones para indicar errores transitorios o si desea usar una respuesta de tipo respuesta de reintento para administrar el comportamiento de reintento.

  • La lógica de detección transitoria dependerá de la API de cliente real que use para invocar las llamadas REST. Algunos clientes, como los de la clase HttpClient más reciente no producirán excepciones para las solicitudes completadas con un código de estado HTTP no correcto.

  • El código de estado HTTP devuelto desde el servicio puede ayudar a indicar si el error es transitorio. Puede que necesite examinar las excepciones generadas por un cliente o el marco de trabajo de reintento para obtener acceso al código de estado o para determinar el tipo de excepción equivalente. Los siguientes códigos HTTP normalmente indican que un reintento es adecuado:

    • Tiempo de espera de solicitud 408
    • 429 Demasiadas solicitudes
    • Error de servidor interno 500
    • Puerta de enlace incorrecta 502
    • Servicio no disponible 503
    • Tiempo de espera de puerta de enlace 504
  • Si la lógica de reintento se basa en excepciones, las siguientes suelen indican un error transitorio donde no se pudo establecer ninguna conexión:

    • WebExceptionStatus.ConnectionClosed
    • WebExceptionStatus.ConnectFailure
    • WebExceptionStatus.Timeout
    • WebExceptionStatus.RequestCanceled
  • En el caso de un estado no disponible del servicio, el servicio podría indicar el retraso adecuado antes de reintentar en el encabezado de respuesta Retry-After o un encabezado personalizado diferente. Los servicios también pueden enviar información adicional como encabezados personalizados o incrustados en el contenido de la respuesta.

  • No lo intente de nuevo para los códigos de estado que representan errores de cliente (errores en el intervalo 4xx) excepto en el caso de 408 Tiempo de espera de solicitud y 429 Demasiadas solicitudes.

  • Pruebe las estrategias y mecanismos de reintento a fondo en una amplia variedad de condiciones, como diferentes estados de red diferente y diferentes cargas de sistema.

Estrategia de reintento

Estos son los tipos típicos de intervalos de estrategia de reintento:

  • Exponencial. Una directiva de reintentos que realiza un número especificado de reintentos, mediante un enfoque de retroceso exponencial aleatorio para determinar el intervalo entre reintentos. Por ejemplo:

    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. Una estrategia de reintentos con un número especificado de reintentos y un intervalo de tiempo incremental entre los reintentos. Por ejemplo:

    retryInterval = TimeSpan.FromMilliseconds(this.initialInterval.TotalMilliseconds +
                    (this.increment.TotalMilliseconds * currentRetryCount));
    
  • LinearRetry. Una directiva de reintentos que realiza un número especificado de reintentos, usando un intervalo de tiempo fijo especificado entre los reintentos. Por ejemplo:

    retryInterval = this.deltaBackoff;
    

Consulte Control de errores transitorios con Polly.

Polly es una biblioteca para controlar mediante programación los reintentos y las estrategias de disyuntor. El proyecto Polly es miembro de .NET Foundation. Para los servicios en los que el cliente no admite los reintentos de forma nativa, Polly es una alternativa válida y evita tener que escribir código de reintentos personalizado, que puede ser difícil de implementar correctamente. Polly también permite el seguimiento de los errores cuando se produzcan, para poder registrar los reintentos.

Pasos siguientes