Przeczytaj w języku angielskim

Udostępnij za pośrednictwem


Bezpieczeństwo wątków i zarządzanie okresem istnienia klienta dla obiektów zestawu Azure SDK

Ten artykuł ułatwia zrozumienie problemów z bezpieczeństwem wątków podczas korzystania z zestawu Azure SDK. W tym artykule omówiono również, jak projekt zestawu SDK ma wpływ na zarządzanie okresem istnienia klienta. Dowiesz się, dlaczego nie jest konieczne usuwanie obiektów klienta zestawu Azure SDK.

Bezpieczeństwo wątkowe

Wszystkie obiekty klienta zestawu Azure SDK są bezpieczne wątkowo i niezależne od siebie. Ten projekt gwarantuje, że ponowne użycie wystąpień klienta jest zawsze bezpieczne, nawet w wątkach. Na przykład poniższy kod uruchamia wiele zadań, ale jest bezpieczny wątkiem:

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

Obiekty modelu używane przez klientów zestawu SDK, niezależnie od tego, czy modele wejściowe, czy wyjściowe, nie są domyślnie bezpieczne wątkowo. Większość przypadków użycia obejmujących obiekty modelu używa tylko jednego wątku. W związku z tym koszt implementacji synchronizacji jako domyślne zachowanie jest zbyt wysoki dla tych obiektów. Poniższy kod ilustruje usterkę, w której uzyskiwanie dostępu do modelu z wielu wątków może spowodować niezdefiniowane zachowanie:

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

Aby uzyskać dostęp do modelu z różnych wątków, musisz zaimplementować własny kod synchronizacji. Na przykład:

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

Okres istnienia klienta

Ponieważ klienci zestawu Azure SDK są bezpieczni wątkowo, nie ma powodu, aby utworzyć wiele obiektów klienta zestawu SDK dla danego zestawu parametrów konstruktora. Traktuj obiekty klienta zestawu Azure SDK jako pojedynczetony po utworzeniu. To zalecenie jest często implementowane przez zarejestrowanie obiektów klienta zestawu Azure SDK jako pojedynczetony w kontenerze Inversion of Control (IoC) aplikacji. Wstrzykiwanie zależności (DI) służy do uzyskiwania odwołań do obiektu klienta zestawu SDK. W poniższym przykładzie pokazano rejestrację pojedynczego obiektu klienta:

var builder = Host.CreateApplicationBuilder(args);

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

builder.Services.AddSingleton(blobServiceClient);

Aby uzyskać więcej informacji na temat implementowania di za pomocą zestawu Azure SDK, zobacz Wstrzykiwanie zależności za pomocą zestawu Azure SDK dla platformy .NET.

Alternatywnie możesz utworzyć wystąpienie klienta zestawu SDK i udostępnić je metodom wymagającym klienta. Chodzi o uniknięcie niepotrzebnych wystąpień tego samego obiektu klienta zestawu SDK z tymi samymi parametrami. To zarówno niepotrzebne, jak i marnudne.

Klienci nie są jednorazowi

Dwa ostatnie pytania, które często pojawiają się:

  • Czy muszę usunąć obiekty klienta zestawu Azure SDK po zakończeniu korzystania z nich?
  • Dlaczego obiekty klienta zestawu Azure SDK oparte na protokole HTTP nie są jednorazowe?

Wewnętrznie wszyscy klienci zestawu Azure SDK używają jednego udostępnionego HttpClient wystąpienia. Klienci nie tworzą żadnych innych zasobów, które muszą być aktywnie zwalniane. Wystąpienie udostępnione HttpClient utrzymuje się przez cały okres istnienia aplikacji.

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

Istnieje możliwość udostępnienia niestandardowego HttpClient wystąpienia obiektu klienta zestawu Azure SDK. W takim przypadku stajesz się odpowiedzialny za zarządzanie HttpClient okresem istnienia i prawidłowe jego usuwanie w odpowiednim czasie.

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

Dalsze wskazówki dotyczące prawidłowego HttpClient zarządzania wystąpieniami i ich dysponowania można znaleźć w HttpClient dokumentacji.

Zobacz też