Richtlijnen voor opnieuw proberen voor Azure-services
De meeste Azure-services en client-SDK's bevatten een mechanisme voor opnieuw proberen. Deze verschillen echter omdat elke service verschillende kenmerken en vereisten heeft, waardoor elk mechanisme voor opnieuw proberen is afgestemd op een specifieke service. Deze gids biedt een samenvatting van de functies van het mechanisme voor opnieuw proberen voor een groot aantal Azure-services en bevat informatie over het gebruiken, aanpassen of uitbreiden van het mechanisme voor de betreffende service.
Raadpleeg Richtlijnen voor opnieuw proberenvoor algemene richtlijnen voor de afhandeling van tijdelijke fouten en het opnieuw proberen van verbindingen en bewerkingen voor services en bronnen.
De volgende tabel geeft een overzicht van de functies voor opnieuw proberen voor de Azure-services die in deze handleiding worden beschreven.
| Service | Mogelijkheden voor opnieuw proberen | Beleidsconfiguratie | Scope | Telemetriefuncties |
|---|---|---|---|---|
| Azure Active Directory | Native in MSAL-bibliotheek | Ingesloten in MSAL-bibliotheek | Intern | Geen |
| Cosmos DB | Systeemeigen in service | Niet-configureerbaar | Globaal | TraceSource |
| Data Lake Store | Systeemeigen in client | Niet-configureerbaar | Afzonderlijke bewerkingen | Geen |
| Event Hubs | Systeemeigen in client | Via programmacode | Client | Geen |
| IoT Hub | Native in client-SDK | Via programmacode | Client | Geen |
| Azure Cache voor Redis | Systeemeigen in client | Via programmacode | Client | TextWriter |
| Zoeken | Systeemeigen in client | Via programmacode | Client | ETW of aangepast |
| Service Bus | Systeemeigen in client | Via programmacode | Naamruimtebeheer, berichtenfactory en client | ETW |
| Service Fabric | Systeemeigen in client | Via programmacode | Client | Geen |
| SQL Database met ADO.NET | Polly | Declaratief en via programmacode | Losse instructies of codeblokken | Aangepast telefoonnummer |
| SQL Database met Entity Framework | Systeemeigen in client | Via programmacode | Algemeen per toepassingsdomein | Geen |
| SQL-Database met Entity Framework Core | Systeemeigen in client | Via programmacode | Algemeen per toepassingsdomein | Geen |
| Storage | Systeemeigen in client | Via programmacode | Client en individuele bewerkingen | TraceSource |
Notitie
Voor de meeste ingebouwde mechanismen voor opnieuw proberen in Azure is er momenteel geen manier om een ander beleid voor opnieuw proberen toe te passen voor verschillende typen fouten of uitzonderingen. U moet een beleid configureren dat de optimale gemiddelde prestaties en beschikbaarheid biedt. Eén manier om het beleid te verfijnen is het analyseren van logboekbestanden om te bepalen welk type tijdelijke fouten optreedt.
Azure Active Directory
Azure Active Directory (Azure Ad) is een uitgebreide cloudoplossing voor identiteits- en toegangsbeheer die kernadreslijstservices, geavanceerd identiteitsbeheer, beveiliging en toegangsbeheer voor toepassingen combineert. Azure AD biedt ontwikkelaars een platform voor identiteitsbeheer waarmee ze toegangsbeheer kunnen bieden voor hun toepassingen, op basis van gecentraliseerd beleid en regels.
Notitie
Zie How to use an Azure VM Managed Service Identity (MSI) for token acquisition (Een Managed Service Identity (MSI) van Azure-VMgebruiken voor het verkrijgen van een token voor richtlijnen voor opnieuw proberen voor Managed Service Identity-eindpunten.
Mechanisme voor opnieuw proberen
Er is een ingebouwd mechanisme voor opnieuw proberen voor Azure Active Directory in de Microsoft Authentication Library (MSAL) . Om onverwachte vergrendelingen te voorkomen, raden we aan dat bibliotheken van derden en toepassingscode mislukte verbindingen niet opnieuw proberen, maar toestaan dat MSAL nieuwe pogingen afwerkt.
Gebruiksrichtlijnen voor opnieuw proberen
Let op de volgende richtlijnen wanneer u Azure Active Directory gebruikt:
- Gebruik indien mogelijk de MSAL-bibliotheek en de ingebouwde ondersteuning voor nieuwe proberen.
- Als u de REST API voor Azure Active Directory gebruikt, moet u de bewerking opnieuw uitvoeren als de resultaatcode 429 (te veel aanvragen) of een fout in het bereik 5xx is. Probeer niet opnieuw voor andere fouten.
- Voor 429-fouten moet u het alleen opnieuw proberen na de tijd die is aangegeven in de header Retry-After.
- Voor 5xx-fouten gebruikt u exponentieel teruggaan, met de eerste poging ten minste 5 seconden na het antwoord.
- Ga niet opnieuw naar fouten dan 429 en 5xx.
Meer informatie
Cosmos DB
Cosmos DB is een volledig beheerde database met meerdere modellen die ondersteuning biedt voor JSON-gegevens zonder schema. De service levert configureerbare en betrouwbare prestaties en een ingebouwde JavaScript-transactieverwerking. Daarbij is de service speciaal ontwikkeld voor in de cloud en is deze flexibel schaalbaar.
Mechanisme voor opnieuw proberen
De klasse CosmosClient voert mislukte pogingen automatisch opnieuw uit. Als u het aantal nieuwe en de maximale wachttijd wilt instellen, configureert u CosmosClientOptions. Uitzonderingen die de client retourneert, vallen buiten het beleid voor opnieuw proberen of zijn geen tijdelijke fouten.
Als een Cosmos DB de client vertraagd, wordt de fout HTTP 429 geretourneerd. Controleer de statuscode in de CosmosException klasse .
Beleidsconfiguratie
In de volgende tabel ziet u de standaardinstellingen voor de klasse CosmosClientOptions.
| Instelling | Standaardwaarde | Beschrijving |
|---|---|---|
| MaxRetryAttemptsOnRateLimitedRequests | 9 | Het maximum aantal nieuwe pogingen als de aanvraag is mislukt doordat Cosmos DB een snelheidsbeperking op de client heeft toegepast. |
| MaxRetryWaitTimeOnRateLimitedRequests | 30 | De maximale tijd voor opnieuw proberen in seconden voor de Azure Cosmos DB service. |
Voorbeeld
CosmosClient cosmosClient = new CosmosClient("connection-string", new CosmosClientOptions()
{
MaxRetryAttemptsOnRateLimitedRequests = 5,
MaxRetryWaitTimeOnRateLimitedRequests = TimeSpan.FromSeconds(15)
});
Telemetrie
Nieuwe pogingen worden vastgelegd als niet-gestructureerde traceringsberichten via een .NET TraceSource. U moet een TraceListener configureren om de gebeurtenissen vast te leggen en ze naar een geschikt doellogboek schrijven.
Als u bijvoorbeeld het volgende aan het bestand App.config toevoegt, worden traceringen gegenereerd in een tekstbestand op dezelfde locatie als het uitvoerbare bestand:
<configuration>
<system.diagnostics>
<switches>
<add name="SourceSwitch" value="Verbose"/>
</switches>
<sources>
<source name="DocDBTrace" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch" >
<listeners>
<add name="MyTextListener" type="System.Diagnostics.TextWriterTraceListener" traceOutputOptions="DateTime,ProcessId,ThreadId" initializeData="CosmosDBTrace.txt"></add>
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
Event Hubs
Azure Event Hubs is een hyperscale telemetrie-opnameservice die miljoenen gebeurtenissen verzamelt, transformeert en opschat.
Mechanisme voor opnieuw proberen
Gedrag voor opnieuw proberen in de clientbibliotheek van Azure Event Hubs wordt geregeld via de eigenschap RetryPolicy van de klasse EventHubClient. Het standaardbeleid voert nieuwe pogingen uit met exponentieel uitstel wanneer Azure Event Hub een tijdelijke EventHubsException of een OperationCanceledException retourneert. Het standaardbeleid voor opnieuw Event Hubs is om het maximaal 9 keer opnieuw uit te voeren met een exponentiële back-offtijd van maximaal 30 seconden.
Voorbeeld
EventHubClient client = EventHubClient.CreateFromConnectionString("[event_hub_connection_string]");
client.RetryPolicy = RetryPolicy.Default;
Meer informatie
.NET Standard-clientbibliotheek voor Azure Event Hubs
IoT Hub
Azure IoT Hub is een service voor het verbinden, bewaken en beheren van apparaten om Internet of Things (IoT)-toepassingen te ontwikkelen.
Mechanisme voor opnieuw proberen
De Apparaat-SDK van Azure IoT kan fouten in het netwerk, protocol of de toepassing detecteren. Op basis van het fouttype controleert de SDK of een nieuwe poging moet worden uitgevoerd. Als de fout kan worden hersteld, begint de SDK het opnieuw te proberen met behulp van het geconfigureerde beleid voor opnieuw proberen.
Het standaardbeleid voor opnieuw proberen is exponentieel af- en uitschakelen met willekeurige jitter, maar dit kan worden geconfigureerd.
Beleidsconfiguratie
Beleidsconfiguratie verschilt per taal. Zie Configuratie van beleid IoT Hub opnieuw proberen voor meer informatie.
Meer informatie
Azure Cache voor Redis
Azure Cache voor Redis is een snelle gegevenstoegang en cacheservice met lage latentie op basis van de populaire opensource Redis-cache. Deze oplossing is veilig, wordt beheerd door Microsoft en is toegankelijk vanaf elke toepassing in Azure.
De richtlijnen in dit gedeelte zijn gebaseerd op het gebruik van de client StackExchange.Redis voor toegang tot de cache. Een lijst met andere geschikte clients vindt u op de Redis-website en deze kunnen verschillende mechanismen voor opnieuw proberen gebruiken.
Houd er rekening mee dat de StackExchange.Redis-client gebruikmaakt van multiplexing via één verbinding. De aanbevolen methode is bij het opstarten van de toepassing een exemplaar van de client te maken en dit exemplaar te gebruiken voor alle bewerkingen met de cache. Daarom wordt de verbinding met de cache slechts één keer gemaakt. Alle richtlijnen in deze sectie hebben dus betrekking op het beleid voor opnieuw proberen voor deze eerste verbinding en niet voor elke bewerking die toegang heeft tot de — cache.
Mechanisme voor opnieuw proberen
De StackExchange.Redis-client maakt gebruik van een klasse voor verbindingsbeheer die is geconfigureerd via een set opties, waaronder:
- ConnectRetry. Het aantal malen dat een mislukte verbinding met de cache opnieuw wordt geprobeerd.
- ReconnectRetryPolicy. De strategie voor opnieuw proberen die moet worden gebruikt.
- ConnectTimeout. De maximale wachttijd in milliseconden.
Beleidsconfiguratie
Beleid voor opnieuw proberen wordt via de programmacode geconfigureerd, waarbij de opties voor de client worden ingesteld voordat u verbinding maakt met de cache. Dit kan worden gedaan door een exemplaar van de klasse ConfigurationOptions te maken, de eigenschappen ervan te vullen en deze door te geven aan de methode Connect.
De ingebouwde klassen ondersteunen lineaire (constante) vertraging en exponentieel uitstel met willekeurige intervallen tussen nieuwe pogingen. U kunt ook een aangepast beleid voor opnieuw proberen maken door de interface IReconnectRetryPolicy te implementeren.
In het volgende voorbeeld wordt een strategie voor opnieuw proberen met exponentieel uitstel geconfigureerd.
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);
U kunt de opties ook opgeven als een tekenreeks en deze doorgeven aan de methode Connect. De eigenschap ReconnectRetryPolicy kan niet op deze manier worden ingesteld, alleen via code.
var options = "localhost,connectRetry=3,connectTimeout=2000";
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);
U kunt opties ook rechtstreeks opgeven wanneer u verbinding maakt met de cache.
var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,connectRetry=3");
Zie Stack Exchange Redis-configuratie in de documentatie over StackExchange.Redis voor meer informatie.
In de volgende tabellen ziet u de standaardinstellingen voor het ingebouwde beleid voor opnieuw proberen.
| Context | Instelling | Standaardwaarde (v 1.2.2) |
Betekenis |
|---|---|---|---|
| ConfigurationOptions | ConnectRetry ConnectTimeout SyncTimeout ReconnectRetryPolicy |
3 Maximaal 5000 ms plus SyncTimeout 1000 LinearRetry 5000 ms |
Het aantal keren dat verbindingspogingen moeten worden herhaald tijdens de eerste verbindingsbewerking. Time-out (ms) voor verbindingsbewerkingen. Geen vertraging tussen nieuwe pogingen. Tijd (ms) die is toegestaan voor synchrone bewerkingen. Elke 5000 ms. opnieuw proberen. |
Notitie
Voor synchrone bewerkingen kan SyncTimeout de end-to-end-latentie vergroten, maar als u de waarde te laag instelt, kan dit leiden tot te lange time-outs. Zie Problemen met Azure Cache voor Redis. In het algemeen dient u synchrone bewerkingen te vermijden en in plaats daarvan asynchrone bewerkingen te gebruiken. Zie Pijplijnen en Multiplexers voor meer informatie.
Gebruiksrichtlijnen voor opnieuw proberen
Houd rekening met de volgende richtlijnen bij het gebruik Azure Cache voor Redis:
- De StackExchange Redis-client beheert zijn een eigen nieuwe pogingen, maar alleen wanneer een verbinding met de cache tot stand wordt gebracht wanneer de toepassing voor het eerst wordt gestart. U kunt de time-out voor de verbinding, het aantal nieuwe pogingen en de tijd tussen nieuwe pogingen om deze verbinding te maken configureren, maar het beleid voor opnieuw proberen geldt niet voor bewerkingen met de cache.
- In plaats van een groot aantal nieuwe pogingen te gebruiken, kunt u overwegen terug te vallen op toegang tot de oorspronkelijke gegevensbron.
Telemetrie
U kunt informatie verzamelen over verbindingen (maar geen andere bewerkingen) met behulp van een TextWriter.
var writer = new StringWriter();
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);
Hieronder ziet u een voorbeeld van de uitvoer die hierbij wordt gegenereerd.
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...
...
Voorbeelden
In het volgende voorbeeld wordt een constante (lineair) vertraging tussen nieuwe pogingen geconfigureerd wanneer de StackExchange.Redis-client wordt geïnitialiseerd. In dit voorbeeld zie u hoe voor het instellen van de configuratie een exemplaar van ConfigurationOptions wordt gebruikt.
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;
}
}
}
}
}
In het volgende voorbeeld wordt de configuratie ingesteld door de opties als een tekenreeks op te geven. De time-out voor de verbinding is de maximale tijd die moet worden gewacht op een verbinding met de cache, niet de vertraging tussen nieuwe pogingen. Houd er rekening mee dat de eigenschap ReconnectRetryPolicy alleen door code kan worden ingesteld.
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;
}
}
}
}
}
Zie Configuratie op de projectwebsite voor meer voorbeelden.
Meer informatie
Azure Search
Azure Search kan worden gebruikt om krachtige en geavanceerde zoekfuncties toe te voegen aan een website of toepassing, de zoekresultaten snel en gemakkelijk aan te passen en uitgebreide en afgestemde rangschikkingsmodellen te creëren.
Mechanisme voor opnieuw proberen
Gedrag voor opnieuw proberen in de Azure Search SDK wordt geregeld door de methode SetRetryPolicy in de klassen SearchServiceClient en SearchIndexClient. Het standaardbeleid voert nieuwe pogingen uit met exponentieel uitstel wanneer Azure Search de reactie 5xx of 408 (time-out van aanvraag) retourneert.
Telemetrie
U kunt traceren met ETW of door een aangepaste traceringsprovider te registreren. Raadpleeg de AutoRest-documentatie voor meer informatie.
Service Bus
Service Bus is een berichtenplatform in de cloud dat losjes gekoppelde berichtuitwisseling met verbeterde schaal en tolerantie biedt voor onderdelen van een toepassing, ongeacht of die in de cloud of on-premises worden gehost.
Mechanisme voor opnieuw proberen
Service Bus implementeert nieuwe proberen met behulp van implementaties van de abstracte klasse RetryPolicy. De naamruimte en enkele configuratiegegevens zijn afhankelijk van Service Bus client-SDK-pakket wordt gebruikt:
| Pakket | Beschrijving | Naamruimte |
|---|---|---|
| Microsoft.Azure.ServiceBus | Azure Service Bus-clientbibliotheek voor .NET Standard. | Microsoft.ServiceBus |
| WindowsAzure.ServiceBus | Dit pakket is de oudere Service Bus-clientbibliotheek. Hiervoor is .NET Framework 4.5.2 vereist. | Microsoft.Azure.ServiceBus |
Beide versies van de clientbibliotheek bieden de volgende ingebouwde implementaties van RetryPolicy :
RetryExponential. Implementeert exponentieel terugkijken.
NoRetry. Voert geen nieuwe proberen uit. Gebruik deze klasse wanneer u geen nieuwe stappen op Service Bus API-niveau nodig hebt, bijvoorbeeld wanneer een ander proces nieuwe stappen beheert als onderdeel van een batchbewerking of bewerking met meerdere stappen.
De RetryPolicy.Default eigenschap retourneert een standaardbeleid van het type RetryExponential . Dit beleidsobject heeft de volgende instellingen:
| Instelling | Standaardwaarde | Betekenis |
|---|---|---|
| MinimalBackoff | 0 | Minimaal uitstelinterval. Toegevoegd aan het interval voor nieuwe poging berekend vanuit deltaBackoff . |
| MaximumBackoff | 30 seconden | Maximaal uitstelinterval. |
| DeltaBackoff | 3 seconden | Uitstelinterval tussen nieuwe pogingen. Veelvouden van deze periode worden gebruikt voor volgende nieuwe pogingen. |
| MaxRetryCount | 5 | Het maximum aantal nieuwe pogingen. (De standaardwaarde is 10 in het WindowsAzure.ServiceBus pakket.) |
Bovendien wordt de volgende eigenschap gedefinieerd in het oudere WindowsAzure.ServiceBus pakket:
| Instelling | Standaardwaarde | Betekenis |
|---|---|---|
| TerminationTimeBuffer | 5 seconden | Nieuwe pogingen worden stopgezet als de resterende tijd kleiner is dan deze waarde. |
Service Bus acties kunnen een reeks uitzonderingen retourneren, vermeld in Service Bus messaging-uitzonderingen. Uitzonderingen die worden geretourneerd Service Bus de eigenschap IsTransient die aangeeft of de client de bewerking opnieuw moet proberen. Het ingebouwde beleid RetryExponential controleert deze eigenschap voordat het opnieuw wordt uitgevoerd.
Als de laatste uitzondering die is aangetroffen ServerBusyException is, voegt het beleid RetryExponential 10 seconden toe aan het berekende interval voor opnieuw proberen. Deze waarde kan niet worden gewijzigd.
Aangepaste implementaties kunnen gebruikmaken van een combinatie van het uitzonderingstype en de eigenschap IsTransient om een meer fijnkeurige controle over acties voor opnieuw proberen te bieden. U kunt bijvoorbeeld een QuotaExceededException detecteren en actie ondernemen om de wachtrij leeg te maken voordat u opnieuw probeert een bericht ernaartoe te verzenden.
Met de volgende code stelt u het beleid voor opnieuw proberen in op Service Bus client met behulp van de Microsoft.Azure.ServiceBus -bibliotheek:
const string QueueName = "queue1";
const string ServiceBusConnectionString = "<your_connection_string>";
var policy = new RetryExponential(
minimumBackoff: TimeSpan.FromSeconds(10),
maximumBackoff: TimeSpan.FromSeconds(30),
maximumRetryCount: 3);
var queueClient = new QueueClient(ServiceBusConnectionString, QueueName, ReceiveMode.PeekLock, policy);
Het beleid voor opnieuw proberen kan niet worden ingesteld op het niveau van een afzonderlijke bewerking. Het is van toepassing op alle bewerkingen voor de client.
Gebruiksrichtlijnen voor opnieuw proberen
Let op de volgende richtlijnen wanneer u Service Bus gebruikt:
- Wanneer u de ingebouwde implementatie van RetryExponential gebruikt, hoeft u geen terugvalbewerking te implementeren aangezien het beleid reageert op ServerBusy-uitzonderingen en automatisch overschakelt naar een geschikte modus voor opnieuw proberen.
- Service Bus ondersteunt een functie genaamd Gekoppelde naamruimten waarmee automatische failover naar een back-upwachtrij in een afzonderlijke naamruimte wordt geïmplementeerd als de wachtrij in de primaire naamruimte mislukt. Berichten in de secundaire wachtrij kunnen worden teruggestuurd naar de primaire wachtrij wanneer deze is hersteld. Deze functie helpt bij het oplossen van tijdelijke fouten. Zie Asynchrone berichtpatronen en hoge beschikbaarheid voor meer informatie.
Overweeg te beginnen met de volgende instellingen voor het opnieuw proberen van bewerkingen. Deze instellingen zijn algemeen gebruik en u moet de bewerkingen bewaken en de waarden afstemmen op uw eigen scenario.
| Context | Voorbeeld van maximale latentie | Beleid voor opnieuw proberen | Instellingen | Uitleg |
|---|---|---|---|---|
| Interactief, gebruikersinterface of voorgrond | 2 seconden* | Exponentieel | MinimumBackoff = 0 MaximumBackoff = 30 sec. DeltaBackoff = 300 ms. TimeBuffer = 300 ms. MaxRetryCount = 2 |
Poging 1: vertraging 0 sec. Poging 2: vertraging ~300 ms. Poging 3: vertraging ~900 ms. |
| Achtergrond of batch | 30 seconden | Exponentieel | MinimumBackoff = 1 MaximumBackoff = 30 sec. DeltaBackoff = 1,75 sec. TimeBuffer = 5 sec. MaxRetryCount = 3 |
Poging 1: vertraging ~1 sec. Poging 2: vertraging ~3 sec. Poging 3: vertraging ~6 sec. Poging 4: vertraging ~13 sec. |
* Exclusief extra vertraging die wordt toegevoegd als de reactie Server bezet wordt ontvangen.
Telemetrie
Service Bus registreert pogingen als ETW-gebeurtenissen in het logboek met een EventSource. U moet een EventListener koppelen aan de gebeurtenisbron om de gebeurtenissen vast te leggen en ze weer te geven in Performance Viewer of naar een geschikt bestemmingslogboek te schrijven. De gebeurtenissen van de nieuwe pogingen hebben de volgende vorm:
Microsoft-ServiceBus-Client/RetryPolicyIteration
ThreadID="14,500"
FormattedMessage="[TrackingId:] RetryExponential: Operation Get:https://retry-tests.servicebus.windows.net/TestQueue/?api-version=2014-05 at iteration 0 is retrying after 00:00:00.1000000 sleep because of Microsoft.ServiceBus.Messaging.MessagingCommunicationException: The remote name could not be resolved: 'retry-tests.servicebus.windows.net'.TrackingId:6a26f99c-dc6d-422e-8565-f89fdd0d4fe3, TimeStamp:9/5/2014 10:00:13 PM."
trackingId=""
policyType="RetryExponential"
operation="Get:https://retry-tests.servicebus.windows.net/TestQueue/?api-version=2014-05"
iteration="0"
iterationSleep="00:00:00.1000000"
lastExceptionType="Microsoft.ServiceBus.Messaging.MessagingCommunicationException"
exceptionMessage="The remote name could not be resolved: 'retry-tests.servicebus.windows.net'.TrackingId:6a26f99c-dc6d-422e-8565-f89fdd0d4fe3,TimeStamp:9/5/2014 10:00:13 PM"
Voorbeelden
Het volgende codevoorbeeld laat zien hoe u het beleid voor opnieuw proberen instelt voor:
- Naamruimtebeheer. Het beleid is van toepassing op alle bewerkingen in de beheerfunctie en kan niet worden overschreven voor afzonderlijke bewerkingen.
- Een berichtenfactory. Het beleid is van toepassing op alle clients die zijn gemaakt op basis van die factory en kan niet worden overschreven wanneer u afzonderlijke clients maakt.
- Een afzonderlijke berichtenclient. Nadat een client is gemaakt, kunt u het beleid voor opnieuw proberen instellen voor die client. Het beleid geldt voor alle bewerkingen op die client.
using System;
using System.Threading.Tasks;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
namespace RetryCodeSamples
{
class ServiceBusCodeSamples
{
private const string connectionString =
@"Endpoint=sb://[my-namespace].servicebus.windows.net/;
SharedAccessKeyName=RootManageSharedAccessKey;
SharedAccessKey=C99..........Mk=";
public async static Task Samples()
{
const string QueueName = "TestQueue";
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
// The namespace manager will have a default exponential policy with 10 retry attempts
// and a 3 second delay delta.
// Retry delays will be approximately 0 sec, 3 sec, 9 sec, 25 sec and the fixed 30 sec,
// with an extra 10 sec added when receiving a ServiceBusyException.
{
// Set different values for the retry policy, used for all operations on the namespace manager.
namespaceManager.Settings.RetryPolicy =
new RetryExponential(
minBackoff: TimeSpan.FromSeconds(0),
maxBackoff: TimeSpan.FromSeconds(30),
maxRetryCount: 3);
// Policies cannot be specified on a per-operation basis.
if (!await namespaceManager.QueueExistsAsync(QueueName))
{
await namespaceManager.CreateQueueAsync(QueueName);
}
}
var messagingFactory = MessagingFactory.Create(
namespaceManager.Address, namespaceManager.Settings.TokenProvider);
// The messaging factory will have a default exponential policy with 10 retry attempts
// and a 3 second delay delta.
// Retry delays will be approximately 0 sec, 3 sec, 9 sec, 25 sec and the fixed 30 sec,
// with an extra 10 sec added when receiving a ServiceBusyException.
{
// Set different values for the retry policy, used for clients created from it.
messagingFactory.RetryPolicy =
new RetryExponential(
minBackoff: TimeSpan.FromSeconds(1),
maxBackoff: TimeSpan.FromSeconds(30),
maxRetryCount: 3);
// Policies cannot be specified on a per-operation basis.
var session = await messagingFactory.AcceptMessageSessionAsync();
}
{
var client = messagingFactory.CreateQueueClient(QueueName);
// The client inherits the policy from the factory that created it.
// Set different values for the retry policy on the client.
client.RetryPolicy =
new RetryExponential(
minBackoff: TimeSpan.FromSeconds(0.1),
maxBackoff: TimeSpan.FromSeconds(30),
maxRetryCount: 3);
// Policies cannot be specified on a per-operation basis.
var session = await client.AcceptMessageSessionAsync();
}
}
}
}
Meer informatie
Service Fabric
Het distribueren van betrouwbare services in een Service Fabric-cluster biedt bescherming tegen de meeste potentiële tijdelijke fouten die in dit artikel worden besproken. Sommige tijdelijke fouten zijn echter nog steeds mogelijk. De naamgevingsservice kan bijvoorbeeld midden in een routeringswijziging zitten wanneer een aanvraag binnenkomt, waardoor een uitzondering wordt gegenereerd. Als dezelfde aanvraag 100 milliseconden later komt, slaagt deze waarschijnlijk wel.
Service Fabric beheert dit soort tijdelijke fouten intern. U kunt een aantal instellingen configureren met behulp van de klasse OperationRetrySettings wanneer u uw services instelt. In de volgende code ziet u een voorbeeld. In de meeste gevallen zou dit niet nodig moeten zijn en zouden de standaardinstellingen moeten voldoen.
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));
Meer informatie
SQL Database met ADO.NET
SQL Database is een gehoste SQL-database die beschikbaar is in allerlei afmetingen en zowel als standaardservice (gedeeld) en als premiumservice (niet gedeeld).
Mechanisme voor opnieuw proberen
SQL Database biedt geen ingebouwde ondersteuning voor nieuwe pogingen wanneer toegang wordt verkregen met behulp van ADO.NET. De retourcodes van aanvragen kunnen echter worden gebruikt om te bepalen waarom een aanvraag mislukt. Zie Resourcelimieten voor Azure SQL Database voor meer informatie over het beperken van SQL Database. Zie SQL-foutcodes voor SQL Database-clienttoepassingen voor een overzicht van relevante foutcodes.
U kunt de bibliotheek Polly gebruiken om nieuwe pogingen voor SQL Database te implementeren. Zie Tijdelijke fouten afhandelen met Polly.
Gebruiksrichtlijnen voor opnieuw proberen
Houd rekening met de volgende richtlijnen wanneer u toegang hebt tot SQL Database met behulp van ADO.NET:
- Kies de juiste service-optie (gedeeld of premium). Een gedeeld exemplaar kan te maken krijgen met langere verbindingsvertragingen en meer beperkingen dan gebruikelijk is doordat andere tenants de gedeelde server gebruiken. Als meer voorspelbare prestaties en betrouwbaardere bewerkingen met een lage latentie zijn vereist, kunt u overwegen de premiumoptie te kiezen.
- Zorg ervoor dat u nieuwe pogingen uitvoert op het juiste niveau of met de juiste scope om te voorkomen dat niet-idempotente bewerkingen inconsistentie in de gegevens veroorzaken. In het ideale geval moeten alle bewerkingen idempotent zijn, zodat ze kunnen worden herhaald zonder inconsistentie te veroorzaken. Als dat niet het geval is, moet de nieuwe poging worden uitgevoerd op een niveau of met een scope waarbij alle gerelateerde wijzigingen ongedaan gemaakt kunnen worden als een bewerking mislukt, bijvoorbeeld binnen een transactionele scope. Zie Basisbeginselen gegevenstoegangslaag cloudservice: afhandeling van tijdelijke fouten voor meer informatie.
- Een strategie met een vast interval wordt niet aanbevolen voor gebruik met Azure SQL Database, met uitzondering van interactieve scenario's waarin er slechts enkele nieuwe pogingen zijn met zeer korte intervallen. In plaats daarvan kunt u overwegen voor de meeste scenario's een strategie met exponentieel uitstel te gebruiken.
- Kies een geschikte waarde voor de time-outs voor verbinding en opdrachten bij het definiëren van verbindingen. Een te korte time-out kan leiden tot voortijdige verbroken verbindingen wanneer de database bezet is. Een te lange time-out kan verhinderen dat de logica voor nieuwe pogingen correct werkt doordat te lang wordt gewacht voordat een mislukte verbinding wordt gedetecteerd. De waarde van de time-out is een onderdeel van de end-to-end-latentie. Deze wordt effectief opgeteld bij de vertraging voor nieuwe pogingen die is opgegeven in het beleid voor opnieuw proberen voor elke nieuwe poging.
- Sluit de verbinding na een bepaald aantal nieuwe pogingen, zelfs als u een logica met exponentieel uitstel gebruikt en probeer het opnieuw met een nieuwe verbinding. Als u dezelfde bewerking meerdere malen probeert met dezelfde verbinding, kan dit bijdragen aan verbindingsproblemen. Zie Basisbeginselen gegevenstoegangslaag cloudservice: afhandeling van tijdelijke fouten voor een voorbeeld van deze techniek.
- Wanneer gegroepeerde verbindingen worden gebruikt (de standaardinstelling), bestaat de kans dat dezelfde verbinding wordt gekozen in de groep, zelfs nadat een verbinding is gesloten en opnieuw is geopend. Als dit het geval is, is één manier om dit te verhelpen de methode ClearPool van de klasse SqlConnection aan te roepen om de verbinding te markeren als niet herbruikbaar. U mag dit echter alleen doen nadat meerdere verbindingspogingen zijn mislukt en alleen als u de specifieke klasse van tijdelijke fouten tegenkomt, zoals SQL-time-outs (foutcode -2) met betrekking tot mislukte verbindingen.
- Als de code voor gegevenstoegang gebruikmaakt van transacties die zijn geïnitieerd als exemplaren van TransactionScope, moet de logica voor opnieuw proberen de verbinding opnieuw openen en een nieuwe transactiescope starten. Daarom moet het codeblok dat opnieuw kan worden geprobeerd, de volledige scope van de transactie omvatten.
Overweeg te beginnen met de volgende instellingen voor het opnieuw proberen van bewerkingen. Deze instellingen zijn voor algemeen gebruik en u moet de bewerkingen bewaken en de waarden afstemmen op uw eigen scenario.
| Context | Voorbeelddoel E2E max. latentie |
Strategie voor opnieuw proberen | Instellingen | Waarden | Uitleg |
|---|---|---|---|---|---|
| Interactief, UI of voorgrond |
2 sec. | FixedInterval | Aantal pogingen Interval tussen nieuwe pogingen Eerste snelle poging |
3 500 ms true |
Poging 1, vertraging 0 sec. Poging 2, vertraging 500 ms Poging 3, vertraging 500 ms |
| Achtergrond of batch |
30 sec. | ExponentialBackoff | Aantal pogingen Min. uitstel Max. uitstel Delta-uitstel Eerste snelle poging |
5 0 sec. 60 sec. 2 sec. onjuist |
Poging 1, vertraging 0 sec. Poging 2, vertraging ~2 sec. Poging 3, vertraging ~6 sec. Poging 4, vertraging ~14 sec. Poging 5, vertraging ~30 sec. |
Notitie
Voor de beoogde end-to-end-latentie wordt uitgegaan van de standaardtime-out voor verbindingen met de service. Als u langere verbindingstime-outs opgeeft, wordt de end-to-end-latentie uitgebreid met deze extra tijd voor elke nieuwe poging.
Voorbeelden
In deze sectie wordt beschreven hoe u Polly kunt gebruiken om toegang te krijgen tot Azure SQL Database met behulp van een set beleidsregels voor opnieuw proberen die zijn geconfigureerd in de klasse Policy.
De volgende code toont een uitbreidingsmethode op de klasse SqlCommand die ExecuteAsync aanroept met exponentieel uitstel.
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);
}
Deze asynchrone uitbreidingsmethode kan als volgt worden gebruikt.
var sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = "[some query]";
using (var reader = await sqlCommand.ExecuteReaderWithRetryAsync())
{
// Do something with the values
}
Meer informatie
Zie de handleiding voor prestaties en elasticiteit voor algemene SQL Database over het Azure SQL Database van uw prestaties en elasticiteit.
SQL Database met Entity Framework 6
SQL Database is een gehoste SQL-database die beschikbaar is in allerlei afmetingen en zowel als standaardservice (gedeeld) en als premiumservice (niet gedeeld). Entity Framework is een object-relationele mapper waarmee .NET-ontwikkelaars kunnen werken met relationele gegevens met behulp van domeinspecifieke objecten. In dit geval is de meeste code voor gegevenstoegang die ontwikkelaars gewoonlijk moeten schrijven, niet meer nodig.
Mechanisme voor opnieuw proberen
Ondersteuning voor opnieuw proberen wordt geboden bij het openen van SQL Database met Entity Framework 6.0 en hoger via een mechanisme met de naam Verbindings resiliency /retry logic. De belangrijkste functies van het mechanisme voor opnieuw proberen zijn:
- De primaire abstrahering is de interface IDbExecutionStrategy. Deze interface:
- Hiermee definieert u synchrone en asynchrone execute-methoden.
- Definieert klassen die rechtstreeks kunnen worden gebruikt of kunnen worden geconfigureerd in een databasecontext als standaardstrategie of die kunnen worden toegewezen aan een providernaam of aan een providernaam en servernaam. Wanneer dit is geconfigureerd in een context, worden nieuwe pogingen uitgevoerd op het niveau van afzonderlijke databasebewerkingen, waarvan er mogelijk meerdere zijn voor een bepaalde contextbewerking.
- Definieert wanneer moet worden geprobeerd een mislukte verbinding opnieuw tot stand te brengen en hoe.
- Het bevat verschillende ingebouwde implementaties van de interface IDbExecutionStrategy:
- Standaardinstelling: geen nieuwe poging.
- Standaard voor SQL Database (automatisch): geen nieuwe poging, maar inspecteert uitzonderingen en verpakt deze met suggesties voor het gebruik van SQL Database strategie.
- Standaard voor SQL Database: exponentieel (overgenomen van basisklasse) plus SQL Database detectielogica.
- Hiermee wordt een strategie voor exponentieel uitstel met willekeurige intervallen geïmplementeerd.
- De ingebouwde klassen voor opnieuw proberen zijn stateful en zijn niet thread-veilig. Ze kunnen echter opnieuw worden gebruikt nadat de huidige bewerking is voltooid.
- Als het opgegeven aantal nieuwe pogingen wordt overschreden, worden de resultaten verpakt in een nieuwe uitzondering. Hierbij komt niet de huidige uitzondering naar boven.
Beleidsconfiguratie
Ondersteuning voor nieuwe pogingen wordt geboden bij toegang tot SQL Database met behulp van Entity Framework 6.0 en hoger. Beleid voor opnieuw proberen wordt geconfigureerd via programmacode. De configuratie kan niet per bewerking worden gewijzigd.
Wanneer u een strategie in de context als standaard configureert, geeft u een functie op die een nieuwe strategie op aanvraag maakt. De volgende code laat zien hoe u een configuratieklasse voor opnieuw proberen maakt die de basisklasse DbConfiguration uitbreidt.
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)));
}
}
U kunt deze vervolgens opgeven als de standaardstrategie voor opnieuw proberen voor alle bewerkingen met de methode SetConfiguration van het exemplaar van DbConfiguration wanneer de toepassing wordt gestart. Standaard detecteert en gebruikt EF de configuratieklasse.
DbConfiguration.SetConfiguration(new BloggingContextConfiguration());
U kunt de configuratieklasse voor opnieuw proberen voor een context opgeven door de contextklasse te voorzien van het kenmerk DbConfigurationType. Als u echter slechts één configuratieklasse hebt, gebruikt EF deze zonder de noodzaak om de context toe te voegen.
[DbConfigurationType(typeof(BloggingContextConfiguration))]
public class BloggingContext : DbContext
Als u andere strategieën voor opnieuw proberen moet gebruiken voor specifieke bewerkingen of als u nieuwe pogingen voor bepaalde bewerkingen wilt uitschakelen, kunt u een configuratieklasse maken waarmee u strategieën kunt onderbreken of afwisselen door een vlag te stellen in de CallContext. De configuratieklasse kan deze vlag gebruiken om tussen strategieën te schakelen of om de strategie die u opgeeft uit te schakelen en een standaardstrategie te gebruiken. Zie Uitvoeringsstrategie opschorten (EF6 en meer) voor meer informatie.
Een andere methode voor het gebruik van specifieke strategieën voor opnieuw proberen bestaat eruit een exemplaar van de vereiste strategieklasse te maken en de gewenste instellingen aan te leveren via parameters. Vervolgens start u de methode 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()
);
De eenvoudigste manier om de klasse DbConfiguration te gebruiken, is deze te zoeken in dezelfde assembly als de klasse DbContext. Dit is echter niet geschikt wanneer dezelfde context is vereist in verschillende scenario's, zoals verschillende interactieve en achtergrondstrategieën voor opnieuw proberen. Als de verschillende contexten worden uitgevoerd in afzonderlijke toepassingsdomeinen, kunt u de ingebouwde ondersteuning voor het opgeven van configuratieklassen in het configuratiebestand gebruiken of deze expliciet instellen met behulp van code. Als de verschillende contexten moeten worden uitgevoerd in hetzelfde toepassingsdomein, is een aangepaste oplossing vereist.
Zie Op code gebaseerde configuratie (EF6 en meer) voor meer informatie.
In de volgende tabel ziet u de standaardinstellingen voor het ingebouwde beleid voor opnieuw proberen bij gebruik van EF6.
| Instelling | Standaardwaarde | Betekenis |
|---|---|---|
| Beleid | Exponentieel | Exponentieel uitstel. |
| MaxRetryCount | 5 | Het maximum aantal nieuwe pogingen. |
| MaxDelay | 30 seconden | De maximale wachttijd tussen nieuwe pogingen. Deze waarde heeft geen invloed op de manier waarop de reeks vertragingen wordt berekend. Deze definieert enkel een bovengrens. |
| DefaultCoefficient | 1 seconde | De coëfficiënt voor de berekening van het exponentiële uitstel. Deze waarde kan niet worden gewijzigd. |
| DefaultRandomFactor | 1.1 | De vermenigvuldigingsfactor die wordt gebruikt om een willekeurige vertraging voor elk item toe te voegen. Deze waarde kan niet worden gewijzigd. |
| DefaultExponentialBase | 2 | De vermenigvuldigingsfactor die wordt gebruikt om de volgende vertraging te berekenen. Deze waarde kan niet worden gewijzigd. |
Gebruiksrichtlijnen voor opnieuw proberen
Houd rekening met de volgende richtlijnen wanneer u toegang hebt tot SQL Database met EF6:
Kies de juiste service-optie (gedeeld of premium). Een gedeeld exemplaar kan te maken krijgen met langere verbindingsvertragingen en meer beperkingen dan gebruikelijk is doordat andere tenants de gedeelde server gebruiken. Als voorspelbare prestaties en betrouwbare bewerkingen met een lage latentie zijn vereist, kunt u overwegen de premiumoptie te kiezen.
Een strategie met een vast interval wordt niet aanbevolen voor gebruik met Azure SQL Database. Gebruik in plaats daarvan een strategie voor exponentieel uitstel omdat de service overbelast zijn kan en langere vertragingen meer tijd voor herstel bieden.
Kies een geschikte waarde voor de time-outs voor verbinding en opdrachten bij het definiëren van verbindingen. Baseer de time-out zowel op het ontwerp van uw zakelijke logica als op tests. Mogelijk moet u deze waarde na verloop van tijd wijzigen als de gegevensvolumes of de bedrijfsprocessen veranderen. Een te korte time-out kan leiden tot voortijdige verbroken verbindingen wanneer de database bezet is. Een te lange time-out kan verhinderen dat de logica voor nieuwe pogingen correct werkt doordat te lang wordt gewacht voordat een mislukte verbinding wordt gedetecteerd. De waarde van de time-out is een onderdeel van de end-to-end-latentie, hoewel u niet eenvoudig kunt bepalen hoeveel opdrachten worden uitgevoerd wanneer de context wordt opgeslagen. U kunt de standaardtime-out wijzigen door de eigenschap CommandTimeout van het exemplaar van DbContext in te stellen.
Entity Framework ondersteunt configuraties voor nieuwe pogingen die zijn gedefinieerd in configuratiebestanden. Voor een maximale flexibiliteit in Azure moet u echter overwegen de configuratie via de programmacode in de toepassing te maken. De specifieke parameters voor het beleid voor opnieuw proberen, zoals het aantal nieuwe pogingen en de intervallen hiertussen, kunnen worden opgeslagen in het configuratiebestand van de service en tijdens de uitvoering worden gebruikt om het juiste beleid te maken. Zo is het mogelijk dat de instellingen veranderen zonder dat de toepassing opnieuw moet worden opgestart.
Overweeg te beginnen met de volgende instellingen voor het opnieuw proberen van bewerkingen. U kunt de vertraging tussen pogingen niet opgeven (deze staat vast en wordt gegenereerd als een exponentiële reeks). U kunt alleen de maximale waarden opgeven, zoals hier wordt weergegeven, tenzij u een aangepaste strategie voor opnieuw proberen maakt. Deze instellingen zijn algemeen gebruik en u moet de bewerkingen controleren en de waarden afstemmen op uw eigen scenario.
| Context | Voorbeelddoel E2E max. latentie |
Beleid voor opnieuw proberen | Instellingen | Waarden | Uitleg |
|---|---|---|---|---|---|
| Interactief, UI of voorgrond |
2 seconden | Exponentieel | MaxRetryCount MaxDelay |
3 750 ms |
Poging 1, vertraging 0 sec. Poging 2, vertraging 750 ms Poging 3, vertraging 750 ms |
| Achtergrond of batch |
30 seconden | Exponentieel | MaxRetryCount MaxDelay |
5 12 seconden |
Poging 1, vertraging 0 sec. Poging 2, vertraging ~1 sec. Poging 3, vertraging ~3 sec. Poging 4, vertraging ~7 sec. Poging 5, vertraging ~12 sec. |
Notitie
Voor de beoogde end-to-end-latentie wordt uitgegaan van de standaardtime-out voor verbindingen met de service. Als u langere verbindingstime-outs opgeeft, wordt de end-to-end-latentie uitgebreid met deze extra tijd voor elke nieuwe poging.
Voorbeelden
Het volgende codevoorbeeld definieert een eenvoudige oplossing voor gegevenstoegang die gebruikmaakt van Entity Framework. Er wordt een specifieke strategie voor opnieuw proberen ingesteld door een exemplaar van een klasse genaamd BlogConfiguration te definiëren die DbConfiguration uitbreidt.
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();
}
}
}
}
Meer voorbeelden van het gebruik van Entity Framework mechanisme voor opnieuw proberen vindt u in Verbindings resiliency /retry logic.
Meer informatie
SQL Database met Entity Framework Core
Entity Framework Core is een object-relationele mapper waarmee .NET Core-ontwikkelaars kunnen werken met gegevens met behulp van domeinspecifieke objecten. In dit geval is de meeste code voor gegevenstoegang die ontwikkelaars gewoonlijk moeten schrijven, niet meer nodig. Deze versie van Entity Framework is helemaal opnieuw geschreven en neemt niet automatisch alle functies van EF6.x over.
Mechanisme voor opnieuw proberen
Ondersteuning voor opnieuw proberen wordt geboden bij het openen van SQL Database met Entity Framework Core via een mechanisme dat verbindings resiliency wordt genoemd. Verbindingstolerantie is geïntroduceerd in EF Core 1.1.0.
De primaire abstrahering is de interface IExecutionStrategy. De uitvoeringsstrategie voor SQL Server, inclusief SQL Azure, is op de hoogte van de typen uitzonderingen die opnieuw kunnen worden geprobeerd en heeft praktische standaardinstellingen voor het maximum aantal nieuwe pogingen, de vertraging tussen pogingen enzovoort.
Voorbeelden
De volgende code maakt automatische nieuwe pogingen mogelijk bij de configuratie van het object DbContext, dat een sessie met de database vertegenwoordigt.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=EFMiscellaneous.ConnectionResiliency;Trusted_Connection=True;",
options => options.EnableRetryOnFailure());
}
De volgende code laat zien hoe u een transactie met automatische nieuwe pogingen uitvoert met behulp van een uitvoeringsstrategie. De transactie is gedefinieerd in een gemachtigde. Als er een tijdelijke fout optreedt, roept de uitvoeringsstrategie de gemachtigde opnieuw aan.
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
Azure Storage zijn blobopslag, bestanden en opslagwachtrijen.
Blobs, wachtrijen en bestanden
De klasse ClientOptions is het basistype voor alle clientoptietypen en maakt verschillende algemene clientopties beschikbaar, zoals Diagnostische gegevens, Opnieuw proberen, Transport. Als u de clientconfiguratieopties wilt bieden om verbinding te maken met Azure Queue, Blob en File Storage moet u het bijbehorende afgeleide type gebruiken. In het volgende voorbeeld gebruikt u de klasse QueueClientOptions (afgeleid van ClientOptions) om een client te configureren om verbinding te maken met Azure Queue Service. De eigenschap Opnieuw proberen is de set opties die kan worden opgegeven om te beïnvloeden hoe nieuwe pogingen worden gedaan en hoe een fout in aanmerking komt om opnieuw te worden geprobeerd.
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);
Tabelondersteuning
Notitie
WindowsAzure. Storage Nuget-pakket is afgeschaft. Zie Microsoft.Azure.Cosmos.Table Nuget-pakket voor ondersteuning van Azure-tabel
Mechanisme voor opnieuw proberen
Nieuwe pogingen worden uitgevoerd op het niveau van de afzonderlijke REST-bewerking en vormen een integraal onderdeel van de implementatie van de client-API. De SDK voor clientopslag gebruikt klassen die de IExtendedRetryPolicy-interface implementeren.
De ingebouwde klassen bieden ondersteuning voor lineair (constante vertraging) en exponentieel met willekeurige intervallen tussen nieuwe pogingen. Er is ook een beleid voor niet opnieuw proberen dat kan worden gebruikt als een ander proces nieuwe pogingen op een hoger niveau afhandelt. U kunt echter uw eigen klassen voor opnieuw proberen implementeren als u specifieke eisen hebt die niet worden aangeboden door de ingebouwde klassen.
Alternatieve nieuwe pogingen schakelen tussen de primaire en secundaire locatie van de opslagservice als u geografisch redundante opslag met leestoegang (RA-GRS) gebruikt en het resultaat van de aanvraag een fout is die opnieuw kan worden geprobeerd. Zie Redundantieopties voor Azure Storage voor meer informatie.
Beleidsconfiguratie
Beleid voor opnieuw proberen wordt geconfigureerd via programmacode. Een gebruikelijke procedure is een exemplaar van TableRequestOptions, BlobRequestOptions, FileRequestOptions of QueueRequestOptions te maken en te vullen.
TableRequestOptions interactiveRequestOption = new TableRequestOptions()
{
RetryPolicy = new LinearRetry(TimeSpan.FromMilliseconds(500), 3),
// For Read-access geo-redundant storage, use PrimaryThenSecondary.
// Otherwise set this to PrimaryOnly.
LocationMode = LocationMode.PrimaryThenSecondary,
// Maximum execution time based on the business use case.
MaximumExecutionTime = TimeSpan.FromSeconds(2)
};
Dit exemplaar van de aanvraagopties kan vervolgens worden ingesteld op de client en alle bewerkingen met de client gebruiken de opgegeven aanvraagopties.
client.DefaultRequestOptions = interactiveRequestOption;
var stats = await client.GetServiceStatsAsync();
U kunt de aanvraagopties op de client overschrijven door een gevuld exemplaar van de klasse voor aanvraagopties door te geven aan verwerkingsmethoden.
var stats = await client.GetServiceStatsAsync(interactiveRequestOption, operationContext: null);
U gebruikt een exemplaar van OperationContext om de code op te geven die moet worden uitgevoerd wanneer een nieuwe poging plaatsvindt en wanneer een bewerking is voltooid. Deze code kan informatie over de bewerking verzamelen voor gebruik in logboeken en telemetrie.
// Set up notifications for an operation
var context = new OperationContext();
context.ClientRequestID = "some request id";
context.Retrying += (sender, args) =>
{
// Collect retry information
};
context.RequestCompleted += (sender, args) =>
{
// Collect operation completion information
};
var stats = await client.GetServiceStatsAsync(null, context);
Het uitgebreide beleid voor opnieuw proberen geeft niet alleen aan of een fout geschikt is voor een nieuwe poging, maar retourneert ook een RetryContext-object dat het aantal nieuwe pogingen en de resultaten van de laatste aanvraag aangeeft en aangeeft of de volgende poging gebeurt op de primaire of secundaire locatie (zie de tabel hieronder voor details). De eigenschappen van het object RetryContext kunnen worden gebruikt om te bepalen of en wanneer een nieuwe poging moet worden gedaan. Zie Methode IExtendedRetryPolicy.Evaluate voor meer informatie.
In de volgende tabellen ziet u de standaardinstellingen voor het ingebouwde beleid voor opnieuw proberen.
Aanvraagopties:
| Instelling | Standaardwaarde | Betekenis |
|---|---|---|
| MaximumExecutionTime | Geen | Maximale uitvoeringstijd voor de aanvraag, inclusief alle potentiële nieuwe pogingen. Als deze niet is opgegeven, is de hoeveelheid tijd die een aanvraag mag duren onbeperkt. Met andere woorden, de aanvraag reageert mogelijk niet meer. |
| ServerTimeout | Geen | Time-outinterval op de server voor de aanvraag (de waarde wordt afgerond op seconden). Als dit niet wordt opgegeven, wordt de standaardwaarde gebruikt voor alle aanvragen naar de server. Meestal kunt u deze instelling het beste weglaten, zodat de standaardwaarde voor de server wordt gebruikt. |
| LocationMode | Geen | Als het opslagaccount is gemaakt met de replicatieoptie Geografisch redundante opslag met leestoegang (RA-GRS), kunt u de locatiemodus gebruiken om aan te geven welke locatie de aanvraag moet ontvangen. Als PrimaryThenSecondary bijvoorbeeld is opgegeven, worden aanvragen altijd eerst naar de primaire locatie verzonden. Als een aanvraag mislukt, wordt deze verzonden naar de secundaire locatie. |
| RetryPolicy | ExponentialPolicy | Zie hieronder voor meer informatie over elke optie. |
Exponentieel beleid:
| Instelling | Standaardwaarde | Betekenis |
|---|---|---|
| maxAttempt | 3 | Aantal nieuwe pogingen. |
| deltaBackoff | 4 seconden | Uitstelinterval tussen nieuwe pogingen. Veelvouden van dit interval, met inbegrip van een willekeurig element, worden gebruikt voor de volgende pogingen. |
| MinBackoff | 3 seconden | Wordt opgeteld bij alle intervallen voor nieuwe pogingen, berekend vanaf deltaBackoff. Deze waarde kan niet worden gewijzigd. |
| MaxBackoff | 120 seconden | MaxBackoff wordt gebruikt als het berekende interval tussen nieuwe pogingen groter is dan MaxBackoff. Deze waarde kan niet worden gewijzigd. |
Lineair beleid:
| Instelling | Standaardwaarde | Betekenis |
|---|---|---|
| maxAttempt | 3 | Aantal nieuwe pogingen. |
| deltaBackoff | 30 seconden | Uitstelinterval tussen nieuwe pogingen. |
Gebruiksrichtlijnen voor opnieuw proberen
Houd rekening met de volgende richtlijnen wanneer u toegang hebt tot Azure-opslagservices met behulp van de API voor de opslagclient:
Gebruik het ingebouwde beleid voor opnieuw proberen van Microsoft.Azure. Storage. RetryPolicies-naamruimte waar ze geschikt zijn voor uw vereisten. In de meeste gevallen is dit beleid toereikend.
Gebruik het beleid ExponentialRetry in batchbewerkingen, achtergrondtaken of niet-interactieve scenario's. In deze scenario's kunt u doorgaans meer tijd voor het herstellen van de service toestaan, met als gevolg een grotere kans dat de — bewerking uiteindelijk slaagt.
Overweeg de eigenschap MaximumExecutionTime van de parameter RequestOptions op te geven om de totale uitvoeringstijd te bewerken, maar houd rekening met het type en de grootte van de bewerking wanneer u een time-outwaarde kiest.
Als u een aangepaste nieuwe poging moet implementeren, maak dan geen wrappers rondom de klassen van de opslagclient. Gebruik in plaats daarvan de mogelijkheden om het bestaande beleid uit te breiden via de interface IExtendedRetryPolicy.
Als u geografisch redundante opslag met leestoegang (RA-GRS) gebruikt, kunt u LocationMode gebruiken om op te geven dat nieuwe pogingen toegang hebben tot de secundaire alleen-lezen kopie van de opslag als de primaire toegang mislukt. Wanneer u deze optie gebruikt, moet u er echter voor zorgen dat uw toepassing correct werkt met gegevens die mogelijk verlopen zijn als de replicatie van de primaire opslag nog niet is voltooid.
Overweeg te beginnen met de volgende instellingen voor het opnieuw proberen van bewerkingen. Deze instellingen zijn voor algemeen gebruik en u moet de bewerkingen bewaken en de waarden afstemmen op uw eigen scenario.
| Context | Voorbeelddoel E2E max. latentie |
Beleid voor opnieuw proberen | Instellingen | Waarden | Uitleg |
|---|---|---|---|---|---|
| Interactief, UI of voorgrond |
2 seconden | Lineair | maxAttempt deltaBackoff |
3 500 ms |
Poging 1, vertraging 500 ms Poging 2, vertraging 500 ms Poging 3, vertraging 500 ms |
| Achtergrond of batch |
30 seconden | Exponentieel | maxAttempt deltaBackoff |
5 4 seconden |
Poging 1, vertraging ~3 ms Poging 2, vertraging ~7 sec. Poging 3, vertraging ~15 sec. |
Telemetrie
Nieuwe pogingen worden geregistreerd in een TraceSource. U moet een TraceListener configureren om de gebeurtenissen vast te leggen en ze naar een geschikt doellogboek schrijven. U kunt TextWriterTraceListener of XmlWriterTraceListener gebruiken om de gegevens naar een logboekbestand te schrijven, EventLogTraceListener gebruiken om te schrijven naar het Windows-gebeurtenislogboek of EventProviderTraceListener om traceergegevens naar het ETW-subsysteem te schrijven. U kunt ook automatischflushing van de buffer configureren en de uitgebreidheid van gebeurtenissen die worden geregistreerd (bijvoorbeeld Fout, Waarschuwing, Informatief en Uitgebreid). Zie Logboekregistratie op de client inschakelen met de .NET-opslagclientbibliotheek voor meer informatie.
Bewerkingen kunnen een exemplaar van OperationContext ontvangen dat de gebeurtenis Retrying beschikbaar stelt om aangepaste telemetrielogica te koppelen. Zie De gebeurtenis OperationContext.Retrying voor meer informatie.
Voorbeelden
Het volgende codevoorbeeld laat zien hoe u twee exemplaren van TableRequestOptions maakt met verschillende instellingen voor opnieuw proberen: een voor interactieve aanvragen en een voor achtergrondaanvragen. Vervolgens worden in het voorbeeld op de client twee beleidsregels voor opnieuw proberen zo ingesteld dat ze worden toegepast voor alle aanvragen, en wordt ook de interactieve strategie voor een specifieke aanvraag zo ingesteld dat deze voorrang heeft op de standaardinstellingen die zijn toegepast op de client.
using System;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Table;
namespace RetryCodeSamples
{
class AzureStorageCodeSamples
{
private const string connectionString = "UseDevelopmentStorage=true";
public async static Task Samples()
{
var storageAccount = CloudStorageAccount.Parse(connectionString);
TableRequestOptions interactiveRequestOption = new TableRequestOptions()
{
RetryPolicy = new LinearRetry(TimeSpan.FromMilliseconds(500), 3),
// For Read-access geo-redundant storage, use PrimaryThenSecondary.
// Otherwise set this to PrimaryOnly.
LocationMode = LocationMode.PrimaryThenSecondary,
// Maximum execution time based on the business use case.
MaximumExecutionTime = TimeSpan.FromSeconds(2)
};
TableRequestOptions backgroundRequestOption = new TableRequestOptions()
{
// Client has a default exponential retry policy with 4 sec delay and 3 retry attempts
// Retry delays will be approximately 3 sec, 7 sec, and 15 sec
MaximumExecutionTime = TimeSpan.FromSeconds(30),
// PrimaryThenSecondary in case of Read-access geo-redundant storage, else set this to PrimaryOnly
LocationMode = LocationMode.PrimaryThenSecondary
};
var client = storageAccount.CreateCloudTableClient();
// Client has a default exponential retry policy with 4 sec delay and 3 retry attempts
// Retry delays will be approximately 3 sec, 7 sec, and 15 sec
// ServerTimeout and MaximumExecutionTime are not set
{
// Set properties for the client (used on all requests unless overridden)
// Different exponential policy parameters for background scenarios
client.DefaultRequestOptions = backgroundRequestOption;
// Linear policy for interactive scenarios
client.DefaultRequestOptions = interactiveRequestOption;
}
{
// set properties for a specific request
var stats = await client.GetServiceStatsAsync(interactiveRequestOption, operationContext: null);
}
{
// Set up notifications for an operation
var context = new OperationContext();
context.ClientRequestID = "some request id";
context.Retrying += (sender, args) =>
{
// Collect retry information
};
context.RequestCompleted += (sender, args) =>
{
// Collect operation completion information
};
var stats = await client.GetServiceStatsAsync(null, context);
}
}
}
}
Meer informatie
Azure Storage voor beleid voor opnieuw proberen van clientbibliotheek
Storage Clientbibliotheek 2.0: beleid voor opnieuw proberen implementeren
Algemene richtlijnen voor REST en opnieuw proberen
Houd rekening met het volgende bij het openen van Azure- of services van derden:
Gebruik een systematische aanpak voor het beheer van nieuwe pogingen, mogelijk als herbruikbare code, zodat u een consistente methodologie kunt toepassen voor alle clients en alle oplossingen.
Overweeg het gebruik van een framework voor opnieuw proberen, zoals Polly, om nieuwe proberen te beheren als de doelservice of client geen ingebouwd mechanisme voor opnieuw proberen heeft. Dit helpt u een consistent gedrag voor opnieuw proberen te implementeren en kan een geschikte strategie voor de doelservice zijn. Mogelijk moet u echter aangepaste code voor opnieuw proberen maken voor services die niet standaard gedrag vertonen, die niet afhankelijk zijn van uitzonderingen om tijdelijke fouten aan te geven of als u een antwoord voor opnieuw proberen wilt gebruiken om gedrag voor opnieuw proberen te beheren.
De tijdelijke detectielogica is afhankelijk van de daadwerkelijke client-API die u gebruikt voor de REST-aanroepen. Sommige clients, zoals de nieuwere klasse HttpClient, genereren geen uitzonderingen voor voltooide aanvragen met een HTTP-statuscode voor een niet-geslaagde bewerking.
De HTTP-statuscode die door de service wordt geretourneerd, kan aangeven of de fout tijdelijk is. Mogelijk moet u de uitzonderingen die worden gegenereerd door een client of het framework onderzoeken om toegang te krijgen tot de statuscode of om het equivalente type uitzondering te bepalen. De volgende HTTP-codes geven meestal aan dat een nieuwe poging toepasselijke is:
- 408 Time-out van aanvraag
- 429 Te veel aanvragen
- 500 Interne serverfout
- 502 Ongeldige gateway
- 503 Service niet beschikbaar
- 504 Time-out van gateway
Als u uw logica voor nieuwe pogingen baseert op uitzonderingen, geeft het volgende doorgaans een tijdelijke fout aan als er geen verbinding tot stand kan worden gebracht:
- WebExceptionStatus.ConnectionClosed
- WebExceptionStatus.ConnectFailure
- WebExceptionStatus.Timeout
- WebExceptionStatus.RequestCanceled
In het geval dat de status van een service niet beschikbaar is, kan de service de juiste vertraging voordat het opnieuw wordt geprobeerd, aangeven in de antwoordheader Retry-After of een andere aangepaste header. Services kunnen aanvullende informatie ook verzenden als aangepaste headers of ingesloten in de inhoud van de reactie.
Doe het niet opnieuw voor statuscodes die clientfouten vertegenwoordigen (fouten in het bereik 4xx), met uitzondering van een time-out van 408-aanvragen en 429 te veel aanvragen.
Test uw strategieën en mechanismen voor opnieuw proberen grondig in allerlei omstandigheden, zoals verschillende netwerkstatussen en wisselende systeembelastingen.
Strategieën voor opnieuw proberen
De volgende zijn standaardsoorten intervallen voor strategieën voor opnieuw proberen:
Exponentieel. Een beleid voor opnieuw proberen dat een opgegeven aantal nieuwe pogingen uitvoert, met behulp van een gerandomiseerde exponentiële back-off-benadering om het interval tussen nieuwe pogingen te bepalen. Bijvoorbeeld:
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);Incrementele. Een strategie voor opnieuw proberen met een opgegeven aantal nieuwe pogingen en een incrementeel tijdsinterval tussen nieuwe pogingen. Bijvoorbeeld:
retryInterval = TimeSpan.FromMilliseconds(this.initialInterval.TotalMilliseconds + (this.increment.TotalMilliseconds * currentRetryCount));LinearRetry. Een beleid voor opnieuw proberen dat een opgegeven aantal nieuwe pogingen uitvoert, met behulp van een opgegeven vast tijdsinterval tussen nieuwe poging. Bijvoorbeeld:
retryInterval = this.deltaBackoff;
Tijdelijke fouten afhandelen met Polly
Polly is een bibliotheek voor het programmatisch afhandelen van nieuwe en circuitafbreekingsstrategieën. Het Polly-project maakt deel uit van de .NET Foundation. Voor services waarbij de client geen systeemeigen ondersteuning voor nieuwe pogingen biedt, is Polly een bruikbaar alternatief, waarbij u geen aangepaste code voor nieuwe pogingen hoeft te schrijven die mogelijk moeilijk correct kan worden geïmplementeerd. Polly biedt ook een manier om fouten te traceren wanneer deze zich voordoen, zodat u nieuwe pogingen kunt vastleggen.