Zabezpečení vláken a správa životnosti klientů pro objekty sady Azure SDK
Tento článek vám pomůže porozumět problémům se zabezpečením vláken při používání sady Azure SDK. Popisuje také, jak návrh sady SDK ovlivňuje správu životnosti klienta. Dozvíte se, proč není nutné odstraňovat objekty klienta Azure SDK.
Bezpečnost vlákna
Všechny klientské objekty sady Azure SDK jsou bezpečné pro přístup z více vláken a nezávisle na sobě. Tento návrh zajišťuje, aby opakované používání klientských instancí bylo vždy bezpečné i napříč vlákny. Například následující kód spustí několik úloh, ale je bezpečný pro vlákno:
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));
}
Objekty modelu používané klienty SADY SDK bez ohledu na to, jestli vstupní nebo výstupní modely, nejsou ve výchozím nastavení bezpečné pro přístup z více vláken. Většina případů použití zahrnující objekty modelu používá pouze jedno vlákno. Proto náklady na implementaci synchronizace jako výchozího chování jsou pro tyto objekty příliš vysoké. Následující kód znázorňuje chybu, při které přístup k modelu z více vláken může způsobit nedefinované chování:
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);
Pokud chcete získat přístup k modelu z různých vláken, musíte implementovat vlastní synchronizační kód. Příklad:
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);
Životnost klienta
Vzhledem k tomu, že klienti Sady Azure SDK jsou v bezpečí z více vláken, není důvod vytvářet pro danou sadu parametrů konstruktoru více klientských objektů sady SDK. Po vytvoření zacházejte s klientskými objekty Sady Azure SDK jako s jedním objektem. Toto doporučení se běžně implementuje registrací klientských objektů azure SDK jako singletonů v kontejneru Inversion of Control (IoC) aplikace. Injektáž závislostí (DI) se používá k získání odkazů na objekt klienta sady SDK. Následující příklad ukazuje registraci objektu klienta singleton:
var builder = Host.CreateApplicationBuilder(args);
var endpoint = builder.Configuration["SecretsEndpoint"];
var blobServiceClient = new BlobServiceClient(
new Uri(endpoint), new DefaultAzureCredential());
builder.Services.AddSingleton(blobServiceClient);
Další informace o implementaci DI se sadou Azure SDK najdete v tématu Injektáž závislostí pomocí sady Azure SDK pro .NET.
Případně můžete vytvořit instanci klienta sady SDK a poskytnout ji metodám, které vyžadují klienta. Cílem je vyhnout se zbytečným instancím stejného objektu klienta sady SDK se stejnými parametry. Je to zbytečné i plýtvání.
Klienti nejsou na jedno použití
Mezi poslední otázky, které se často objeví, patří:
- Musím po dokončení jejich používání odstranit klientské objekty sady Azure SDK?
- Proč nejsou objekty klienta Azure SDK založené na HTTP na jedno použití?
Všichni klienti Azure SDK interně používají jednu sdílenou HttpClient
instanci. Klienti nevytvoří žádné další prostředky, které je potřeba aktivně uvolnit. Sdílená HttpClient
instance trvá po celou dobu životnosti aplikace.
// 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));
Vlastní instanci klientského objektu HttpClient
sady Azure SDK je možné poskytnout. V tomto případě se stanete zodpovědným za správu životnosti HttpClient
a jeho správné likvidaci ve správný čas.
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();
Další pokyny pro správnou správu a odstraňování HttpClient
instancí najdete v HttpClient dokumentaci.