Guide du mécanisme de nouvelle tentative relatif aux services Azure

La plupart des services Azure et des kits de développement logiciel (SDK) client incluent un mécanisme de nouvelle tentative. Cependant, ceux-ci diffèrent, car chaque service a des exigences et des caractéristiques différentes, et donc chaque mécanisme de nouvelle tentative est réglé sur un service spécifique. Ce guide récapitule les fonctionnalités du mécanisme de nouvelle tentative pour la plupart des services Azure. Il comprend des informations qui vous aideront à utiliser, adapter ou étendre le mécanisme de nouvelle tentative pour ce service.

Pour obtenir des instructions générales sur la gestion des erreurs temporaires, des nouvelles tentatives de connexion et des opérations en fonction des services et des ressources, consultez Guide sur les nouvelles tentatives.

Le tableau suivant récapitule les fonctionnalités de nouvelle tentative pour les services Azure décrits dans ce guide.

Service Fonctionnalités de nouvelle tentative Configuration de la stratégie Portée Fonctionnalités de télémétrie
Microsoft Entra ID Natives dans la bibliothèque MSAL Incorporée dans la bibliothèque MSAL Interne None
Azure Cosmos DB Native dans le service Non configurable Global TraceSource
Data Lake Store Native dans le client Non configurable Opérations individuelles None
Event Hubs Native dans le client Par programme Client None
IoT Hub Natif dans le SDK client Par programme Client None
Azure Cache pour Redis Native dans le client Par programme Client TextWriter
Recherche Native dans le client Par programme Client ETW ou personnalisé
Service Bus Native dans le client Par programme Gestionnaire d’espace de noms, fabrique de messagerie et client ETW
Service Fabric Native dans le client Par programme Client None
Base de données SQL avec ADO.NET Polly Déclarative et par programme Instructions uniques ou blocs de code Custom
Base de données SQL avec Entity Framework Native dans le client Par programme Globale par domaine d’application None
SQL Database avec Entity Framework Core Native dans le client Par programme Globale par domaine d’application None
Stockage Native dans le client Par programme Opérations individuelles et du client TraceSource

Notes

Pour la plupart des mécanismes de nouvelle tentative intégrés Azure, il n’existe actuellement aucune manière d’appliquer une autre stratégie de nouvelle tentative selon le type d’erreur ou d’exception. Vous devez configurer une stratégie qui fournit les performances et la disponibilité moyennes optimales. Une façon d’ajuster la stratégie consiste à analyser les fichiers journaux pour déterminer le type d’erreurs temporaires qui se produisent.

Microsoft Entra ID

Microsoft Entra ID est une solution cloud complète de gestion et des accès et des identités qui combine des services d’annuaire essentiels, une gouvernance avancée des identités, des services de sécurité et une gestion des accès aux applications. Microsoft Entra ID offre également aux développeurs une plateforme de gestion des identités pour fournir un contrôle d’accès à leurs applications, en fonction d’une stratégie et de règles centralisées.

Remarque

Pour obtenir des conseils de nouvelle tentative sur les points de terminaison Managed Service Identity, consultez Utilisation d’une identité du service administré (MSI) d’une machine virtuelle Azure pour obtenir des jetons.

Mécanisme de nouvelle tentative

Il existe un mécanisme de nouvelle tentative intégré pour Microsoft Entra ID dans la Bibliothèque d’authentification Microsoft (MSAL). Pour éviter les verrouillages imprévus, il est recommandé que les bibliothèques et le code d’application tiers n’effectuent pas de nouvelles tentatives pour les connexions ayant échoué, mais autorisent la bibliothèque MSAL à gérer les nouvelles tentatives.

Guide d’utilisation des nouvelles tentatives

Respectez les consignes suivantes lors de l’utilisation de Microsoft Entra ID :

  • Dans la mesure du possible, utilisez la bibliothèque MSAL et la prise en charge intégrée des nouvelles tentatives.
  • Si vous utilisez l’API REST pour Microsoft Entra ID, renouvelez l’opération si le code résultat est 429 (Trop de requêtes) ou si vous rencontrez une erreur comprise dans la plage 5xx. N’effectuez pas de nouvelles tentatives pour les autres erreurs.
  • Pour les erreurs 429, ne réessayez qu’après l’heure indiquée dans l’en-tête Retry-after (nouvelle tentative après).
  • Pour les erreurs 5xx, utilisez le backoff exponentiel, avec la première tentative d’au moins 5 secondes après la réponse.
  • N’effectuez pas de nouvelles tentatives pour les erreurs autres que 429 et 5xx.

Étapes suivantes

Azure Cosmos DB

Azure Cosmos DB est une base de données multimodèle entièrement gérée qui prend en charge les données JSON sans schéma. Elle offre des performances configurables et fiables, un traitement transactionnel JavaScript natif et est conçue pour le cloud avec une mise à l’échelle élastique.

Mécanisme de nouvelle tentative

Les SDK Azure Cosmos DB effectuent automatiquement une nouvelle tentative lorsqu’ils rencontrent certaines erreurs. En outre, les applications utilisateur sont encouragées à avoir leurs propres stratégies de nouvelle tentative. Pour obtenir la liste complète des conditions d’erreur et des nouvelles tentatives possibles, consultez le guide de conception des applications résilientes avec les SDK Azure Cosmos DB.

Télémétrie

Selon le langage de votre application, les diagnostics et les données de télémétrie peuvent être exposés comme des journaux ou des propriétés promues dans les réponses d’opération. Pour plus d’informations, consultez la section « Capturer les diagnostics » dans SDK C# Azure Cosmos DB et SDK Java Azure Cosmos DB.

Data Lake Store

Data Lake Storage Gen2 fait du stockage Azure la base pour créer des lacs de données d’entreprise sur Azure. Data Lake Storage Gen2 vous permet de gérer facilement de grandes quantités de données.

La Bibliothèque de client Fichier Lac de données du Stockage Azure intègre toutes les fonctionnalités nécessaires aux développeurs, scientifiques et analystes de données pour stocker des données, quels qu’en soient la taille, la forme ou le débit, et d’effectuer tous types de traitements et d’analyses sur différentes plateformes et dans différents langages.

Mécanisme de nouvelle tentative

Le DataLakeServiceClient vous permet de gérer les ressources et les systèmes de fichiers du service Lac de données Azure. Le compte de stockage fournit l’espace de noms de niveau supérieur pour le service Lac de données. Lorsque vous créez le client, vous pouvez fournir ses options de configuration pour la connexion au service Lac de données Azure (DataLakeClientOptions). Le DataLakeClientOptions inclut une propriété Retry (héritée d’Azure.Core.ClientOptions) qui peut être configurée (classe RetryOptions).

Télémétrie

La Surveillance de l’utilisation et des performances du stockage Azure est un élément important de l’opérationnalisation de votre service. Il peut s’agir d’opérations fréquentes, d’opérations avec une latence élevée ou d’opérations entraînant une limitation côté service.

Toutes les données de télémétrie de votre compte de stockage sont disponibles via les Journaux de Stockage Azure dans Azure Monitor. Cette fonctionnalité intègre votre compte de stockage avec Log Analytics et Event Hubs, tout en vous permettant d’archiver les journaux dans un autre compte de stockage. Pour consulter la liste complète des journaux de métriques et de ressources et le schéma associé, consultez Informations de référence sur les données de supervision du stockage Azure.

Event Hubs

Azure Event Hubs est un service d’ingestion de télémétrie hyperscale qui collecte, transforme et stocke des millions d’événements.

Mécanisme de nouvelle tentative

Le comportement du mécanisme de nouvelle tentative dans la bibliothèque de client Azure Event Hubs est contrôlé par la propriété RetryPolicy sur la classe EventHubClient. La stratégie par défaut effectue de nouvelles tentatives avec un backoff exponentiel quand Azure Event Hubs retourne une exception temporaire EventHubsException ou OperationCanceledException. La stratégie de nouvelles tentatives par défaut pour Event Hubs consiste à réessayer jusqu’à 9 fois avec une durée de backoff exponentiel pouvant atteindre 30 secondes.

Exemple

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

Étapes suivantes

Bibliothèque de client Azure Event Hubs pour .NET

IoT Hub

Azure IoT Hub est un service de connexion, de surveillance et de gestion des appareils pour le développement d’applications IoT.

Mécanisme de nouvelle tentative

Azure IoT device SDK peut détecter les erreurs dans le réseau, le protocole ou l’application. Selon le type d’erreur, le Kit de développement logiciel vérifie si une nouvelle tentative doit être effectuée. Si l’erreur est récupérable, le Kit de développement lance une nouvelle tentative à l’aide de la stratégie de nouvelle tentative configurée.

La stratégie de nouvelle tentative par défaut est temporisation exponentielle avec instabilité aléatoire, mais celle-ci peut être configurée.

Configuration de la stratégie

La configuration de la stratégie diffère selon le langage. Pour plus d’informations, consultez Configuration de la stratégie de nouvelles tentatives IoT Hub.

Étapes suivantes

Cache Azure pour Redis

Azure Cache pour Redis est un service de cache de faible latence et d’accès aux données rapide basé sur le cache Redis open source connu. Il est sécurisé, managé par Microsoft et accessible à partir de n’importe quelle application dans Azure.

Les instructions de cette section sont basées sur l’utilisation du client StackExchange.Redis pour accéder au cache. Vous trouverez une liste des autres clients appropriés sur le site web de Redis, qui peuvent avoir des mécanismes de nouvelle tentative différents.

Le client StackExchange.Redis utilise le multiplexage via une seule connexion. L’utilisation recommandée consiste à créer une instance du client au démarrage de l’application et à utiliser cette instance pour toutes les opérations sur le cache. Pour cette raison, la connexion au cache est effectuée une seule fois. Ainsi, toutes les instructions de cette section sont associées à la stratégie de nouvelle tentative pour cette connexion initiale et non pour chaque opération qui accède au cache.

Mécanisme de nouvelle tentative

Le client StackExchange.Redis utilise une classe de gestionnaire de connexions qui est configurée par le biais d’un ensemble d’options, incluant :

  • ConnectRetry. Nombre de fois où une connexion au cache ayant échoué fera l’objet d’une nouvelle tentative.
  • ReconnectRetryPolicy. Stratégie de nouvelle tentative à utiliser.
  • ConnectTimeout. Temps d’attente maximal en millisecondes.

Configuration de la stratégie

Les stratégies de nouvelle tentative sont configurées par programme en définissant les options pour le client avant de se connecter au cache. Cela peut être effectué en créant une instance de la classe ConfigurationOptions, en remplissant ses propriétés et en la transmettant à la méthode Connect.

Les classes intégrées prennent en charge un délai linéaire (constant) et une interruption exponentielle avec des intervalles avant nouvelle tentative aléatoires. Vous pouvez également créer une stratégie de nouvelle tentative personnalisée en implémentant l’interface IReconnectRetryPolicy.

L’exemple ci-après configure une stratégie de nouvelle tentative à l’aide d’une interruption exponentielle.

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

Vous pouvez également spécifier les options sous forme de chaîne et la transmettre à la méthode Connect . La propriété ReconnectRetryPolicy ne peut pas être définie de cette manière, mais uniquement via du code.

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

Vous pouvez également spécifier des options directement lorsque vous vous connectez au cache.

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

Pour plus d’informations, consultez la section concernant la configuration de StackExchange.Redis dans la documentation de StackExchange.Redis.

Le tableau suivant présente les paramètres par défaut pour la stratégie de nouvelle tentative intégrée.

Contexte Paramètre Valeur par défaut
(v 1.2.2)
Signification
ConfigurationOptions ConnectRetry

ConnectTimeout

SyncTimeout

ReconnectRetryPolicy
3

5 000 ms maximum plus SyncTimeout
1 000

LinearRetry 5 000 ms
Le nombre de répétitions de tentatives de connexion pendant l’opération de connexion initiale.
Délai d’attente (ms) pour les opérations de connexion. Pas un délai entre chaque tentative.
Temps (ms) pour permettre des opérations synchrones.

Nouvelle tentative toutes les 5 000 ms.

Notes

Dans le cas des opérations synchrones, le paramètre SyncTimeout peut augmenter la latence de bout en bout, mais la définition d’une valeur trop faible risque d’entraîner des délais d’expiration excessifs. Consultez Résolution des problèmes Azure Cache pour Redis. En règle générale, utilisez des opérations asynchrones plutôt que des opérations synchrones. Pour plus d’informations, consultez Pipelines et multiplexeurs.

Guide d’utilisation des nouvelles tentatives

Respectez les consignes suivantes lors de l’utilisation d’Azure Cache pour Redis :

  • Le client StackExchange Redis gère ses propres nouvelles tentatives, mais uniquement lors de l’établissement d’une connexion au cache au premier démarrage de l’application. Vous pouvez configurer le délai de connexion, le nombre de nouvelles tentatives et l’intervalle entre les nouvelles tentatives pour établir cette connexion, mais la stratégie de nouvelles tentatives ne s’applique pas aux opérations effectuées sur le cache.
  • Au lieu d’utiliser un grand nombre de nouvelles tentatives, envisagez une solution de secours en accédant plutôt à la source de données d’origine.

Télémétrie

Vous pouvez collecter des informations sur les connexions (mais pas sur d’autres opérations) à l’aide d’un élément TextWriter.

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

Vous trouverez ci-dessous un exemple de la sortie générée.

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

Exemples

L’exemple de code ci-après configure un délai (linéaire) constant entre les nouvelles tentatives lors de l’initialisation du client StackExchange.Redis. Cet exemple indique comment définir la configuration à l’aide d’une instance 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;
                }
            }
        }
    }
}

L’exemple ci-après définit la configuration en spécifiant les options sous forme de chaîne. Le délai de connexion correspond au temps d’attente maximal autorisé pour la connexion au cache. Il ne s’agit pas du délai entre chaque nouvelle tentative. La propriété ReconnectRetryPolicy peut uniquement être définie via du code.

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

Pour plus d’exemples, consultez Configuration sur le site web de projet.

Étapes suivantes

Azure Search permet d’ajouter des fonctionnalités de recherche puissantes et sophistiquées à un site web ou une application, d’ajuster rapidement et aisément les résultats de recherche, et de construire des modèles de classement enrichis et optimisés.

Mécanisme de nouvelle tentative

Azure SDK for .NET comprend une bibliothèque client Azure.Search.Documents de l'équipe Azure SDK qui est fonctionnellement équivalente à la bibliothèque client précédente, Microsoft.Azure.Search.

Le comportement de nouvelle tentative dans lMicrosoft.Azure.Search est contrôlé par la méthode SetRetryPolicy sur les classes SearchServiceClient et SearchIndexClient. La stratégie par défaut effectue une nouvelle tentative avec temporisation exponentielle lorsque Recherche Azure renvoie une réponse 5xx ou 408 (Délai d’expiration de la demande).

Le comportement des nouvelles tentatives dans Azure.Search.Documents est contrôlé par SearchClientOptions (il fait partie du constructeur SearchClient) dans la propriété Retry, qui appartient à la classe Azure.Core.RetryOptions (où toutes les configurations sont disponibles).

Télémétrie

Effectuez le suivi avec ETW ou via l’inscription d’un fournisseur de suivi personnalisé. Pour plus d’informations, consultez la documentation AutoRest.

Service Bus

Service Bus est une plate-forme de messagerie cloud qui propose l’échange de messages d’une façon faiblement couplée avec une amélioration de la mise à l’échelle et de la résilience pour les composants d’une application, si cette dernière est hébergée dans le cloud ou sur site.

Mécanisme de nouvelle tentative

L’espace de noms et certains des détails de configuration dépendent du package du kit de développement logiciel (SDK) client Service Bus utilisé :

Package Description Espace de noms
Azure.Messaging.ServiceBus Bibliothèque de client Azure Service Bus pour .NET Azure.Messaging.ServiceBus
WindowsAzure.ServiceBus Ce package correspondant à l’ancienne bibliothèque de client Service Bus. Il requiert .NET Framework 4.5.2. Microsoft.Azure.ServiceBus

Guide d’utilisation des nouvelles tentatives

La propriété ServiceBusRetryOptions spécifie les options de nouvelles tentatives pour l’objet ServiceBusClient :

Paramètre Valeur par défaut Signification
CustomRetryPolicy Stratégie de nouvelles tentatives personnalisée à utiliser à la place des valeurs d’option individuelles.
Retarder 0,8 seconde Délai entre les nouvelles tentatives pour une approche fixe, ou délai sur lequel baser les calculs pour une approche reposant sur un backoff.
MaxDelay 60 secondes Délai maximal admissible entre les nouvelles tentatives.
MaxRetries 3 Nombre maximal de nouvelles tentatives avant de considérer que l’opération associée a échoué.
Mode Exponentielle Approche à utiliser pour calculer les délais de nouvelle tentative.
TryTimeout 60 secondes Durée maximale d’attente pour l’exécution d’une seule tentative, qu’il s’agisse de la première tentative ou d’une nouvelle tentative.

Définissez la propriété Mode pour configurer le ServiceBusRetryMode avec l’une des valeurs suivantes :

Propriété Valeur Description
Exponentielle 1 Les nouvelles tentatives sont retardées en fonction d’une stratégie de backoff, où chaque tentative augmente la durée d’attente avant une nouvelle tentative.
Résolution 0 Les nouvelles tentatives se produisent à intervalles fixes, chaque délai correspondant à une durée cohérente.

Exemple :

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

Télémétrie

Service Bus collecte les mêmes types de données de monitoring que les autres ressources Azure. Vous pouvez superviser Azure Service Bus à l’aide d’Azure Monitor.

Vous disposez également de différentes options pour envoyer de la télémétrie avec les bibliothèques de client Service Bus .NET.

Exemple

L’exemple de code suivant montre comment utiliser le package Azure.Messaging.ServiceBus pour :

  • Définir la stratégie de nouvelles tentatives d’un ServiceBusClient à l’aide d’un nouveau ServiceBusClientOptions.
  • Créer un message avec une nouvelle instance de ServiceBusMessage.
  • Envoyer un message à Service Bus à l’aide de la méthode ServiceBusSender.SendMessageAsync(message).
  • Recevoir des messages à l’aide de ServiceBusReceiver, qui est représenté sous la forme d’objets 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);

Étapes suivantes

Service Fabric

La distribution de services fiables dans un cluster Service Fabric offre une protection contre la plupart des erreurs temporaires potentielles décrites dans cet article. Toutefois, certaines erreurs temporaires restent possibles. Par exemple, si le service d’affectation de noms reçoit une requête au moment précis où il fait l’objet d’un changement de routage, il lève une exception. En revanche, si la même requête arrive 100 millisecondes plus tard, elle aboutira probablement.

Service Fabric gère ce type d’erreur temporaire en interne. Vous pouvez configurer certains paramètres à l’aide de la classe OperationRetrySettings lorsque vous configurez vos services. Le code ci-après présente un exemple. Dans la plupart des situations, cela n’est pas nécessaire, et les paramètres par défaut conviennent.

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

Étapes suivantes

Base de données SQL utilisant ADO.NET

La base de données SQL est une base de données SQL hébergée disponible en différentes tailles et sous forme de service standard (partagé) et premium (non partagé).

Mécanisme de nouvelle tentative

Les bases de données SQL n’intègrent aucune prise en charge pour les nouvelles tentatives en cas d’accès à l’aide d’ADO.NET. Toutefois, les codes de retour issus des demandes peuvent être utilisés pour déterminer le motif d’échec de ces dernières. Pour plus d’informations sur la limitation de SQL Database, consultez Limites des ressources Azure SQL Database. Pour obtenir la liste des codes d’erreur pertinents, consultez l’article Codes d’erreur SQL pour les applications clientes SQL Database.

Vous pouvez utiliser la bibliothèque Polly afin d’implémenter le mécanisme de nouvelles tentatives pour SQL Database. Consultez la section Gestion des erreurs temporaires avec Polly.

Guide d’utilisation des nouvelles tentatives

Respectez les consignes suivantes lorsque vous accédez à la base de données SQL à l’aide d’ADO.NET :

  • Choisissez l’option de service appropriée (partagée ou premium). Une instance partagée peut être soumise à des délais de connexion plus longs que d’ordinaire et à des limitations en raison de l’utilisation du serveur partagé par d’autres locataires. Si des performances prévisibles et des opérations fiables à faible latence sont requises, pensez à choisir l’option premium.
  • Veillez à effectuer de nouvelles tentatives au niveau ou à l’étendue qui convient pour éviter les opérations non idempotent à l’origine d’une incohérence dans les données. Idéalement, toutes les opérations doivent être idempotent afin qu’elles puissent être répétées sans entraîner d’incohérence. Quand ce n’est pas le cas, la nouvelle tentative doit être effectuée à un niveau ou dans une étendue qui permet d’annuler tous les changements associés en cas d’échec d’une opération, par exemple, à partir d’une étendue transactionnelle. Pour plus d’informations, consultez Couche d’accès aux données de Cloud Service Fundamentals - Gestion des erreurs temporaires.
  • Il n’est pas recommandé d’utiliser une stratégie à base d’intervalles fixes avec Azure SQL Database, sauf pour les scénarios interactifs comportant seulement quelques nouvelles tentatives à intervalles courts. À la place, utilisez une stratégie de backoff exponentiel pour la plupart des scénarios.
  • Choisissez une valeur appropriée pour les délais d’attente de connexion et de commande lors de la définition des connexions. Un délai d’attente trop court peut entraîner des échecs de connexion prématurés lorsque la base de données est occupée. Un délai d’attente trop long peut empêcher la logique de nouvelle tentative de fonctionner correctement en attendant trop longtemps avant la détection d’un échec de connexion. La valeur du délai d’expiration est un composant de la latence de bout en bout. Il est en fait ajouté au délai de nouvelle tentative spécifié dans la stratégie de nouvelles tentatives pour chaque nouvelle tentative.
  • Fermez la connexion après un certain nombre de nouvelles tentatives, même en cas d’utilisation d’une logique de nouvelle tentative reposant sur un backoff exponentiel, puis retentez l’opération sur une nouvelle connexion. Le fait d’effectuer la même opération à plusieurs reprises sur la même connexion peut être un facteur entraînant des problèmes de connexion. Pour voir un exemple de cette technique, consultez Couche d’accès aux données de Cloud Service Fundamentals - Gestion des erreurs temporaires.
  • Quand le regroupement de connexions est utilisé (valeur par défaut), il peut arriver que la même connexion soit choisie dans le pool, même après la fermeture et la réouverture d’une connexion. Si tel est le cas, il existe une technique permettant de résoudre le problème. Elle consiste à appeler la méthode ClearPool de la classe SqlConnection pour marquer la connexion comme étant non réutilisable. Toutefois, vous ne devez effectuer cette opération qu’après l’échec de plusieurs tentatives de connexion, et uniquement lorsque vous rencontrez la classe spécifique d’erreurs temporaires, relative notamment à des délais d’attente SQL (code d’erreur -2) liés à des connexions défectueuses.
  • Si le code d’accès aux données utilise des transactions lancées en tant qu’instances TransactionScope , la logique de nouvelle tentative doit ouvrir de nouveau la connexion et lancer une nouvelle étendue de transaction. Pour cette raison, le bloc de code renouvelable doit englober l’ensemble de la portée de la transaction.

Pensez à commencer par les paramètres ci-après pour les opérations liées aux nouvelles tentatives. Il s’agit de paramètres généraux. Vous devez par conséquent surveiller les opérations et optimiser les valeurs en fonction de votre propre scénario.

Contexte Exemple de E2E cible
latence maximale
Stratégie de nouvelle tentative Paramètres Valeurs Fonctionnement
Interactif, interface utilisateur,
ou premier plan
2 secondes FixedInterval Nombre de tentatives
Intervalle avant nouvelle tentative
Première nouvelle tentative rapide
3
500 ms
true
Tentative 1 - délai 0 s
Tentative 2 - délai 500 ms
Tentative 3 - délai 500 ms
Arrière-plan
ou lot
30 secondes ExponentialBackoff Nombre de tentatives
Temporisation min
Temporisation max
Temporisation delta
Première nouvelle tentative rapide
5
0 seconde
60 secondes
2 secondes
false
Tentative 1 - délai 0 s
Tentative 2 - délai ~2 s
Tentative 3 - délai ~6 s
Tentative 4 - délai ~14 s
Tentative 5 - délai ~30 s

Notes

Les cibles de latence de bout en bout supposent le délai d’attente par défaut pour les connexions au service. Si vous spécifiez des délais de connexion, la latence de bout en bout sera prolongée de ce temps supplémentaire pour toute nouvelle tentative.

Exemples

Cette section vous indique comment utiliser Polly pour accéder à Azure SQL Database à l’aide d’un ensemble de stratégies de nouvelle tentative configurées dans la classe Policy.

Le code ci-après présente l’utilisation d’une méthode d’extension sur la classe SqlCommand qui appelle ExecuteAsync avec une interruption exponentielle.

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

Cette méthode d’extension asynchrone est utilisable comme suit.

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

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

Étapes suivantes

Base de données SQL utilisant Entity Framework 6

La base de données SQL est une base de données SQL hébergée disponible en différentes tailles et sous forme de service standard (partagé) et premium (non partagé). Entity Framework est un mappeur relationnel objet qui permet aux développeurs .NET de travailler avec des données relationnelles à l’aide d’objets spécifiques de domaine. Il élimine le recours à la plupart du code d’accès aux données que les développeurs doivent généralement écrire.

Mécanisme de nouvelle tentative

La prise en charge de la fonctionnalité de nouvelle tentative est assurée lors de l’accès à SQL Database à l’aide d’Entity Framework 6.0 et version supérieure par le biais d’un mécanisme appelé résilience de connexion/logique de nouvelle tentative. Les principales fonctionnalités de ce mécanisme sont :

  • L’abstraction principale est l’interface IDbExecutionStrategy . Cette interface :
    • Définit les méthodes synchrones et asynchrones Execute.
    • Définit les classes qui peuvent être utilisées directement ou configurées sur un contexte de base de données comme une stratégie par défaut mappée sur un nom de fournisseur ou un nom de fournisseur et un nom de serveur. En cas de configuration sur un contexte, les nouvelles tentatives se produisent au niveau des opérations de base de données individuelles. Il peut y en avoir plusieurs pour une opération de contexte donnée.
    • Définit à quel moment et comment proposer une nouvelle tentative en cas d’échec de connexion.
  • Il inclut plusieurs implémentations intégrées de l’interface IDbExecutionStrategy :
    • Par défaut : aucune nouvelle tentative.
    • Par défaut pour la base de données SQL (automatique) : aucune nouvelle tentative, mais inspecte les exceptions et y inclut la suggestion d’utiliser la stratégie de base de données SQL.
    • Par défaut pour la base de données SQL : exponentielle (héritée de la classe de base) et logique de détection de base de données SQL.
  • Il implémente une stratégie de temporisation exponentielle qui inclut la répartition aléatoire.
  • Les classes de nouvelles tentatives intégrées sont des classes avec état et ne sont pas thread-safe. Toutefois, elles peuvent être réutilisées une fois l’opération en cours terminée.
  • Si le nombre de tentatives spécifié est dépassé, les résultats sont inclus dans une nouvelle exception. Il ne se propage pas à l’exception actuelle.

Configuration de la stratégie

La prise en charge de la nouvelle tentative est assurée lors de l’accès à la base de données SQL à l’aide d’Entity Framework 6.0 et versions ultérieures. Les stratégies de nouvelle tentative sont configurées par programme. La configuration ne peut pas être changée opération par opération.

Lorsque vous configurez une stratégie sur le contexte comme stratégie par défaut, vous définissez une fonction qui crée une nouvelle stratégie à la demande. Le code suivant montre comment vous pouvez créer une classe de configuration de nouvelle tentative qui étend la classe de 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)));
  }
}

Vous pouvez alors la spécifier comme stratégie de nouvelle tentative par défaut pour toutes les opérations à l’aide de la méthode SetConfiguration de l’instance DbConfiguration lorsque l’application démarre. Par défaut, Entity Framework détecte et utilise automatiquement la classe de configuration.

DbConfiguration.SetConfiguration(new BloggingContextConfiguration());

Vous pouvez spécifier la classe de configuration de nouvelle tentative pour un contexte en annotant la classe de contexte avec un attribut DbConfigurationType . Toutefois, si vous avez une seule classe de configuration, Entity Framework l’utilisera sans avoir à annoter le contexte.

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

Si vous devez utiliser des stratégies de nouvelle tentative différentes pour des opérations spécifiques ou désactiver des nouvelles tentatives pour des opérations spécifiques, vous pouvez créer une classe de configuration qui vous permet de suspendre ou d’échanger des stratégies en définissant un indicateur dans le CallContext. La classe de configuration peut utiliser cet indicateur pour changer de stratégie ou désactiver la stratégie indiquée et utilisée comme stratégie par défaut. Pour plus d’informations, consultez Suspendre la stratégie d’exécution (Entity Framework 6 et versions ultérieures).

Une autre technique d’utilisation de stratégies de nouvelle tentative spécifiques pour des opérations individuelles consiste à créer une instance de la classe de stratégie requise et à fournir la configuration requise au moyen de paramètres. Vous pouvez ensuite faire appel à sa méthode 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 façon la plus simple d’utiliser une classe DbConfiguration consiste à la localiser dans le même assembly que la classe DbContext. Toutefois, cela n’est pas approprié quand le même contexte est nécessaire dans différents scénarios, par exemple différentes stratégies de nouvelles tentatives interactives et en arrière-plan. Si les différents contextes s’exécutent dans un AppDomain séparé, vous pouvez utiliser la prise en charge intégrée pour spécifier des classes de configuration dans le fichier de configuration ou la définir explicitement à l’aide de code. Si les différents contextes doivent s’exécuter dans le même AppDomain, une solution personnalisée sera nécessaire.

Pour plus d’informations, consultez Configuration basée sur le code (Entity Framework 6 et versions supérieures).

Le tableau suivant présente les paramètres par défaut pour la stratégie de nouvelle tentative intégrée lors de l’utilisation d’Entity Framework 6.

Paramètre Valeur par défaut Signification
Policy Exponentielle Temporisation exponentielle.
MaxRetryCount 5 Nombre maximal de nouvelles tentatives.
MaxDelay 30 secondes Délai maximal entre les nouvelles tentatives. Cette valeur n’affecte pas le mode de calcul de la série de délais. Elle définit uniquement une limite supérieure.
DefaultCoefficient 1 seconde Coefficient du calcul de temporisation exponentielle. Il n’est pas possible de modifier cette valeur.
DefaultRandomFactor 1.1 Multiplicateur utilisé pour l’ajout d’un délai aléatoire pour chaque entrée. Il n’est pas possible de modifier cette valeur.
DefaultExponentialBase 2 Multiplicateur utilisé pour le calcul du délai suivant. Il n’est pas possible de modifier cette valeur.

Guide d’utilisation des nouvelles tentatives

Respectez les consignes suivantes lorsque vous accédez à la base de données SQL à l’aide d’Entity Framework 6 :

  • Choisissez l’option de service appropriée (partagée ou premium). Une instance partagée peut être soumise à des délais de connexion plus longs que d’ordinaire et à des limitations en raison de l’utilisation du serveur partagé par d’autres locataires. Si des performances prévisibles et des opérations fiables à faible latence sont requises, pensez à choisir l’option premium.

  • Il n’est pas recommandé d’utiliser une stratégie à base d’intervalles fixes avec Azure SQL Database. Utilisez plutôt une stratégie de temporisation exponentielle car le service peut être surchargé et des délais plus longs laissent davantage de temps de récupération.

  • Choisissez une valeur appropriée pour les délais d’attente de connexion et de commande lors de la définition des connexions. Basez le délai d’attente à la fois sur la conception de la logique métier et sur les tests. Vous devrez peut-être modifier cette valeur au fil du temps en fonction de l’évolution des volumes de données ou des processus d’entreprise. Un délai d’attente trop court peut entraîner des échecs de connexion prématurés lorsque la base de données est occupée. Un délai d’attente trop long peut empêcher la logique de nouvelle tentative de fonctionner correctement en attendant trop longtemps avant la détection d’un échec de connexion. La valeur du délai d’expiration est un composant de la latence de bout en bout. Toutefois, vous ne pouvez pas facilement déterminer le nombre de commandes qui seront exécutées au moment de l’enregistrement du contexte. Vous pouvez modifier le délai d’attente par défaut en définissant la propriété CommandTimeout de l’instance DbContext.

  • Entity Framework prend en charge les configurations de nouvelle tentative définies dans les fichiers de configuration. Toutefois, pour une flexibilité maximale sur Azure, vous devez envisager la création de la configuration par programme au sein de l’application. Les paramètres spécifiques pour les stratégies de nouvelle tentative, tels que le nombre de nouvelles tentatives et les intervalles, peuvent être stockés dans le fichier de configuration du service et être utilisés en cours d’exécution pour créer les stratégies appropriées. Cela permet de modifier les paramètres sans avoir à redémarrer l’application.

Pensez à commencer par les paramètres ci-après pour les opérations liées aux nouvelles tentatives. Vous ne pouvez pas spécifier le délai entre les nouvelles tentatives (il est fixe et généré sous forme de séquence exponentielle). Vous ne pouvez spécifier que les valeurs maximales, comme indiqué ici, sauf si vous créez une stratégie de nouvelle tentative personnalisée. Il s’agit de paramètres généraux. Vous devez par conséquent surveiller les opérations et optimiser les valeurs en fonction de votre propre scénario.

Contexte Exemple de E2E cible
latence maximale
Stratégie de nouvelle tentative Paramètres Valeurs Fonctionnement
Interactif, interface utilisateur,
ou premier plan
2 secondes Exponentielle MaxRetryCount
MaxDelay
3
750 ms
Tentative 1 - délai 0 s
Tentative 2 - délai 750 ms
Tentative 3 - délai 750 ms
Arrière-plan
ou lot
30 secondes Exponentielle MaxRetryCount
MaxDelay
5
12 secondes
Tentative 1 - délai 0 s
Tentative 2 - délai ~1 s
Tentative 3 - délai ~3 s
Tentative 4 - délai ~7 s
Tentative 5 - délai 12 s

Notes

Les cibles de latence de bout en bout supposent le délai d’attente par défaut pour les connexions au service. Si vous spécifiez des délais de connexion, la latence de bout en bout sera prolongée de ce temps supplémentaire pour toute nouvelle tentative.

Exemples

L’exemple de code suivant définit une solution d’accès aux données simple qui utilise Entity Framework. Il spécifie une stratégie de nouvelle tentative spécifique par la définition de l’instance d’une classe nommée BlogConfiguration qui étend 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();
            }
        }
    }
}

Vous trouverez plusieurs exemples d’utilisation du mécanisme de nouvelle tentative d’Entity Framework dans Résilience des connexions/logique des nouvelles tentatives.

Base de données SQL utilisant Entity Framework Core

Entity Framework Core est un mappeur Objet Relationnel qui permet aux développeurs .NET Core de travailler avec des données à l’aide d’objets spécifiques du domaine. Il élimine le recours à la plupart du code d’accès aux données que les développeurs doivent généralement écrire. Cette version d’Entity Framework a été écrite à partir de zéro et n’hérite pas automatiquement de toutes les fonctionnalités d’EF6.x.

Mécanisme de nouvelle tentative

La prise en charge du mécanisme de nouvelle tentative est assurée lors de l’accès à SQL Database utilisant Entity Framework Core par le biais d’un mécanisme appelé résilience de connexion. La résilience de connexion a été introduite dans EF Core 1.1.0.

L’abstraction principale est l’interface IExecutionStrategy. La stratégie d’exécution de SQL Server, incluant SQL Azure, tient compte des types d’exceptions qui peuvent faire l’objet de nouvelles tentatives et présente des valeurs par défaut sensibles pour le nombre maximal de nouvelles tentatives, le délai entre deux tentatives, et ainsi de suite.

Exemples

Le code ci-après autorise les nouvelles tentatives automatiques lors de la configuration de l’objet DbContext, qui représente une session avec la base de données.

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

Le code ci-après indique comment exécuter une transaction avec de nouvelles tentatives automatiques à l’aide d’une stratégie d’exécution. La transaction est définie dans un délégué. En cas d’échec passager, la stratégie d’exécution appelle de nouveau le délégué.

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

Stockage Azure

Les services de stockage Azure incluent le stockage des objets blob, les fichiers et les files d’attente de stockage.

Objets blob, files d’attente et fichiers

La classe ClientOptions est le type de base pour tous les types d’option client et expose diverses options client courantes, comme Diagnostics, Retry et Transport. Pour fournir les options de configuration du client pour la connexion à la file d’attente Azure, aux objets Blob et au stockage de fichiers, vous devez utiliser le type dérivé correspondant. Dans l’exemple suivant, vous utilisez la classe QueueClientOptions (dérivée de ClientOptions) pour configurer un client afin qu’il se connecte au service de file d’attente Azure. La propriété Retry est l’ensemble d’options qui peuvent être spécifiées pour influencer la manière dont les nouvelles tentatives sont effectuées et comment un échec peut faire l’objet d’une nouvelle tentative.

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

Prise en charge de table

Notes

Le package Nuget WindowsAzure.Storage et le package Nuget Microsoft.Azure.Cosmos.Table ont été dépréciés. Pour la prise en charge des tables Azure, consultez Package Nuget Azure.Data.Tables

Mécanisme de nouvelle tentative

La bibliothèque cliente est basée sur la bibliothèque Azure Core, qui est une bibliothèque qui fournit des services transversaux à d’autres bibliothèques clientes.

Il existe de nombreuses raisons pour lesquelles un échec peut se produire lorsqu’une application cliente tente d’envoyer une requête réseau à un service. Par exemple, le délai d’attente, les défaillances de l’infrastructure réseau, le rejet de la demande par le service en raison d’une limitation/d’une occupation, la instance de fin du service en raison d’un scale-down du service, la instance de service qui est en panne pour être remplacé par une autre version, le blocage du service en raison d’une exception non prise en charge, etc. En proposant un mécanisme de nouvelle tentative intégré (avec une configuration par défaut que le consommateur peut remplacer), nos SDK et l’application du consommateur deviennent résilients à ces types de défaillances. Notez que certains services facturent de l’argent réel pour chaque demande et que les consommateurs doivent donc être en mesure de désactiver entièrement les nouvelles tentatives s’ils préfèrent économiser de l’argent plutôt que la résilience.

Configuration de la stratégie

Les stratégies de nouvelle tentative sont configurées par programme. La configuration est basée sur la classe RetryOption. Il existe un attribut sur TableClientOptions hérité de ClientOptions

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

Les tableaux ci-après présentent les possibilités pour les stratégies de nouvelle tentative intégrées.

RetryOption

Paramètre Signification
Retarder Délai entre les nouvelles tentatives pour une approche fixe, ou délai sur lequel baser les calculs pour une approche reposant sur un backoff. Si le service fournit un en-tête de réponse Retry-After, la nouvelle tentative suivante est reportée de la durée spécifiée par la valeur d’en-tête.
MaxDelay Délai maximal autorisé entre les nouvelles tentatives lorsque le service ne fournit pas d’en-tête de réponse Retry-After. Si le service fournit un en-tête de réponse Retry-After, la nouvelle tentative suivante est reportée de la durée spécifiée par la valeur d’en-tête.
Mode Approche à utiliser pour calculer les délais de nouvelle tentative.
NetworkTimeout Délai d’expiration appliqué aux opérations réseaux individuelles.

RetryMode

Paramètre Signification
Exponentielle Les nouvelles tentatives sont retardées en fonction d’une stratégie de backoff, où chaque tentative augmente la durée d’attente avant une nouvelle tentative.
MaxDelay Les nouvelles tentatives se produisent à intervalles fixes, chaque délai correspondant à une durée cohérente.

Télémétrie

Le moyen le plus simple d’afficher les journaux consiste à activer la journalisation de console. Pour créer un écouteur de journal du Kit de développement logiciel (SDK) Azure qui génère des messages dans la console, utilisez la méthode AzureEventSourceListener.CreateConsoleLogger.

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

Exemples

L’exécution de l’exemple de code suivant avec l’arrêt de l’émulateur de stockage nous permet de voir des informations sur les nouvelles tentatives dans la 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}.");
        }
    }
}

Instructions générales relatives aux nouvelles tentatives et à REST

Prenez en compte les éléments suivants lors de l’accès aux services Azure ou tiers :

  • Utilisez une approche systématique pour gérer les nouvelles tentatives, peut-être en tant que code réutilisable, afin de pouvoir appliquer une méthodologie cohérente sur tous les clients et toutes les solutions.

  • Pensez à utiliser une infrastructure de nouvelle tentative, telle que Polly pour gérer les nouvelles tentatives si le service cible ou le client ne dispose d’aucun mécanisme de nouvelle tentative intégré. Cela vous permettra d’implémenter un comportement cohérent de nouvelle tentative, et peut fournir une stratégie de nouvelle tentative par défaut appropriée pour le service cible. Toutefois, vous devrez peut-être créer un code de nouvelle tentative personnalisé pour les services ayant un comportement non standard, qui ne repose pas sur les exceptions afin d’indiquer les défaillances temporaires, ou si vous souhaitez utiliser une réponse Retry-Response pour gérer le comportement des nouvelles tentatives.

  • La logique de détection temporaire dépend de l’API client réelle utilisée pour appeler les appels REST. Certains clients, par exemple la nouvelle classe HttpClient, ne lèvent pas d’exceptions pour les requêtes effectuées avec un code d’état HTTP indiquant un échec.

  • Le code d’état HTTP renvoyé par le service peut permettre d’indiquer si l’échec est temporaire. Vous devrez peut-être examiner les exceptions générées par un client ou l’infrastructure de nouvelle tentative pour accéder au code d’état ou pour déterminer le type d’exception équivalent. Les codes HTTP suivants indiquent habituellement qu’une nouvelle tentative est appropriée :

    • 408 Délai d’expiration de la requête
    • 429 Trop de demandes
    • 500 Erreur interne du serveur
    • 502 Passerelle incorrecte
    • 503 Service indisponible
    • 504 Dépassement du délai de la passerelle
  • Si vous basez votre logique de nouvelle tentative sur les exceptions, ce qui suit indique généralement un échec temporaire lorsqu’aucune connexion n’a pu être établie :

    • WebExceptionStatus.ConnectionClosed
    • WebExceptionStatus.ConnectFailure
    • WebExceptionStatus.Timeout
    • WebExceptionStatus.RequestCanceled
  • Dans le cas d’un service à l’état non disponible, le service peut indiquer le délai approprié avant l’exécution d’une nouvelle tentative dans l’en-tête de réponse Retry-After ou dans un en-tête personnalisé différent. Les services peuvent également envoyer des informations supplémentaires sous la forme d’en-têtes personnalisés ou en les intégrant au contenu de la réponse.

  • N’effectuez pas de nouvelles tentatives pour les codes d’état représentant des erreurs du client (erreurs comprises dans la plage 4xx), sauf dans le cas du code 408 indiquant un dépassement du délai d’expiration de la requête et du code 429 indiquant un trop grand nombre de requêtes.

  • Testez minutieusement vos stratégies et mécanismes de nouvelle tentative sous différentes conditions, en utilisant différents états de réseau et en variant les charges du système.

Stratégie de nouvelle tentative

Voici les types d’intervalles de stratégie de nouvelle tentative classiques :

  • Exponentielle. Une stratégie de nouvelle tentative qui effectue un nombre spécifié de tentatives en utilisant une approche de secours exponentielle répartie de manière aléatoire pour déterminer l’intervalle entre deux tentatives. Par exemple :

    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);
    
  • Incrémentielle. Une stratégie de nouvelle tentative avec un nombre spécifié de nouvelles tentatives et un intervalle de temps incrémentiel entre deux tentatives. Par exemple :

    retryInterval = TimeSpan.FromMilliseconds(this.initialInterval.TotalMilliseconds +
                    (this.increment.TotalMilliseconds * currentRetryCount));
    
  • LinearRetry. Une stratégie de nouvelle tentative qui effectue un nombre spécifié de nouvelles tentatives en utilisant un intervalle fixe spécifique entre deux tentatives. Par exemple :

    retryInterval = this.deltaBackoff;
    

Gestion des erreurs temporaires avec Polly

Polly est une bibliothèque permettant de gérer par programmation les nouvelles tentatives et les stratégies de disjoncteur. Le projet Polly est un membre de l’organisation .NET Foundation. Pour les services où le client ne prend pas en charge de manière native les nouvelles tentatives, Polly représente une alternative valide et évite d’avoir à écrire du code de nouvelle tentative personnalisé, qui peut être difficile à implémenter correctement. Polly vous offre également un moyen de tracer les erreurs lorsqu’elles se produisent, ce qui vous permet de journaliser les nouvelles tentatives.

Étapes suivantes