Delen via


Threadbeveiliging en levensduurbeheer van clients voor Azure SDK-objecten

Dit artikel helpt u inzicht te hebben in problemen met threadveiligheid bij het gebruik van de Azure SDK. Ook wordt besproken hoe het ontwerp van de SDK van invloed is op het levensduurbeheer van clients. U leert waarom het niet nodig is om Azure SDK-clientobjecten te verwijderen.

Schroefdraadveiligheid

Alle Azure SDK-clientobjecten zijn thread-veilig en onafhankelijk van elkaar. Dit ontwerp zorgt ervoor dat het hergebruik van clientexemplaren altijd veilig is, zelfs voor threads. Met de volgende code worden bijvoorbeeld meerdere taken gestart, maar is thread veilig:

var client = new SecretClient(
    new Uri("<secrets_endpoint>"), new DefaultAzureCredential());

foreach (var secretName in secretNames)
{
    // Using clients from parallel threads
    Task.Run(() => Console.WriteLine(client.GetSecret(secretName).Value));
}

Modelobjecten die worden gebruikt door SDK-clients, ongeacht of invoer- of uitvoermodellen, niet standaard thread-veilig zijn. De meeste use cases met betrekking tot modelobjecten gebruiken slechts één thread. Daarom zijn de kosten voor het implementeren van synchronisatie als standaardgedrag te hoog voor deze objecten. De volgende code illustreert een fout waarbij het openen van een model vanuit meerdere threads een niet-gedefinieerd gedrag kan veroorzaken:

KeyVaultSecret newSecret = client.SetSecret("secret", "value");

foreach (var tag in tags)
{
    // Don't use model type from parallel threads
    Task.Run(() => newSecret.Properties.Tags[tag] = CalculateTagValue(tag));
}

client.UpdateSecretProperties(newSecret.Properties);

Als u toegang wilt krijgen tot het model vanuit verschillende threads, moet u uw eigen synchronisatiecode implementeren. Voorbeeld:

KeyVaultSecret newSecret = client.SetSecret("secret", "value");

// Code omitted for brevity

foreach (var tag in tags)
{
    Task.Run(() =>
    {
        lock (newSecret)
        {
            newSecret.Properties.Tags[tag] = CalculateTagValue(tag);
        }
    );
}

client.UpdateSecretProperties(newSecret.Properties);

Levensduur van client

Omdat Azure SDK-clients thread-veilig zijn, is er geen reden om meerdere SDK-clientobjecten te maken voor een bepaalde set constructorparameters. Behandelt Azure SDK-clientobjecten als singletons zodra deze zijn gemaakt. Deze aanbeveling wordt meestal geïmplementeerd door Azure SDK-clientobjecten te registreren als singletons in de Inversion of Control-container (IoC) van de app. Afhankelijkheidsinjectie (DI) wordt gebruikt om verwijzingen naar het SDK-clientobject te verkrijgen. In het volgende voorbeeld ziet u een singleton-clientobjectregistratie:

var builder = Host.CreateApplicationBuilder(args);

var endpoint = builder.Configuration["SecretsEndpoint"];
var blobServiceClient = new BlobServiceClient(
    new Uri(endpoint), new DefaultAzureCredential());

builder.Services.AddSingleton(blobServiceClient);

Zie Afhankelijkheidsinjectie met de Azure SDK voor .NET voor meer informatie over het implementeren van DI met de Azure SDK.

U kunt ook een SDK-clientexemplaren maken en deze opgeven voor methoden waarvoor een client is vereist. Het punt is om onnodige instantiëringen van hetzelfde SDK-clientobject met dezelfde parameters te voorkomen. Het is zowel onnodig als verspilling.

Clients zijn niet wegwerpbaar

Twee laatste vragen die vaak ontstaan zijn:

  • Moet ik Azure SDK-clientobjecten verwijderen wanneer ik klaar ben met het gebruik ervan?
  • Waarom worden azure SDK-clientobjecten op basis van HTTP niet weggewerpd?

Intern gebruiken alle Azure SDK-clients één gedeeld exemplaar HttpClient . De clients maken geen andere resources die actief moeten worden vrijgemaakt. Het gedeelde HttpClient exemplaar blijft gedurende de hele levensduur van de toepassing behouden.

// Both clients reuse the shared HttpClient and don't need to be disposed
var blobClient = new BlobClient(new Uri(sasUri));
var blobClient2 = new BlobClient(new Uri(sasUri2));

Het is mogelijk om een aangepast exemplaar van HttpClient een Azure SDK-clientobject op te geven. In dit geval wordt u verantwoordelijk voor het beheren van de HttpClient levensduur en het op het juiste moment op de juiste manier verwijderen.

var httpClient = new HttpClient();

var clientOptions = new BlobClientOptions()
{
    Transport = new HttpClientTransport(httpClient)
};

// Both clients would use the HttpClient instance provided in clientOptions
var blobClient = new BlobClient(new Uri(sasUri), clientOptions);
var blobClient2 = new BlobClient(new Uri(sasUri2), clientOptions);

// Code omitted for brevity

// You're responsible for properly disposing httpClient some time later
httpClient.Dispose();

Meer richtlijnen voor het correct beheren en verwijderen van HttpClient exemplaren vindt u in de HttpClient documentatie.

Zie ook