Threadsicherheit und Verwaltung der Clientlebensdauer für Azure SDK-Objekte
Dieser Artikel hilft Ihnen, Probleme mit der Threadsicherheit bei Verwendung des Azure SDK zu verstehen. Außerdem wird erläutert, wie sich der Entwurf des SDK auf die Verwaltung der Clientlebensdauer auswirkt. Sie erfahren, warum das Löschen von Azure SDK-Clientobjekten nicht erforderlich ist.
Threadsicherheit
Alle Azure SDK-Clientobjekte sind threadsicher und voneinander unabhängig. Durch diesen Entwurf wird sichergestellt, dass die Wiederverwendung von Clientinstanzen auch threadübergreifend stets sicher ist. Der folgende Code startet beispielsweise mehrere Aufgaben, ist aber threadsicher:
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));
}
Von SDK-Clients verwendete Modellobjekte, ob Eingabe- oder Ausgabemodelle, sind standardmäßig nicht threadsicher. In den meisten Anwendungsfällen mit Modellobjekten wird nur ein einziger Thread verwendet. Daher sind die Kosten für die Implementierung der Synchronisierung als Standardverhalten für diese Objekte zu hoch. Der folgende Code veranschaulicht einen Fehler, bei dem der Zugriff auf ein Modell von mehreren Threads aus ein nicht definiertes Verhalten verursachen kann:
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);
Um von verschiedenen Threads aus auf das Modell zuzugreifen, müssen Sie Ihren eigenen Synchronisierungscode implementieren. Zum Beispiel:
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);
Clientlebensdauer
Da Azure SDK-Clients threadsicher sind, gibt es keinen Grund, mehrere SDK-Clientobjekte für einen bestimmten Satz von Konstruktorparametern zu erstellen. Behandeln Sie Azure SDK-Clientobjekte nach der Konstruktion als Singletons. Diese Empfehlung wird üblicherweise durch die Registrierung von Azure SDK Client-Objekten als Singletons im IoC-Container (Inversion of Control) der App umgesetzt. Abhängigkeitsinjektion (Dependency Injection, DI) dient zum Abrufen von Verweisen auf das SDK-Clientobjekt. Das folgende Beispiel zeigt die Registrierung eines Singletonclientobjekts:
var builder = Host.CreateApplicationBuilder(args);
var endpoint = builder.Configuration["SecretsEndpoint"];
var blobServiceClient = new BlobServiceClient(
new Uri(endpoint), new DefaultAzureCredential());
builder.Services.AddSingleton(blobServiceClient);
Weitere Informationen zum Implementieren der Abhängigkeitsinjektion mit dem Azure SDK finden Sie unter Abhängigkeitsinjektion mit dem Azure SDK für .NET.
Alternativ können Sie eine SDK-Clientinstanz erstellen und für Methoden bereitstellen, die einen Client erfordern. Es geht darum, unnötige Instanziierungen des gleichen SDK-Clientobjekts mit den gleichen Parametern zu vermeiden. Dies ist sowohl unnötig als auch unwirtschaftlich.
Clients sind nicht löschbar
Zwei abschließende Fragen, die häufig gestellt werden:
- Muss ich Azure SDK-Clientobjekte löschen, wenn ich sie nicht weiter verwenden möchte?
- Warum sind HTTP-basierte Azure SDK-Clientobjekte nicht löschbar?
Intern nutzen alle Azure SDK-Clients eine einzelne HttpClient
-Instanz gemeinsam. Die Clients erstellen keine anderen Ressourcen, die aktiv freigegeben werden müssen. Die gemeinsam genutzt HttpClient
-Instanz bleibt während der gesamten Lebensdauer der Anwendung erhalten.
// 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));
Es ist möglich, eine benutzerdefinierte Instanz von HttpClient
für ein Azure SDK-Clientobjekt bereitzustellen. In diesem Fall übernehmen Sie die Verantwortung für die Verwaltung der Lebensdauer von HttpClient
und die ordnungsgemäße Löschung zum richtigen Zeitpunkt.
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();
Weitere Anleitungen zum ordnungsgemäßen Verwalten und Löschen von HttpClient
-Instanzen finden Sie in der Dokumentation zu HttpClient.