Внедрение зависимостей с помощью пакета Azure SDK для .NET
В этой статье показано, как зарегистрировать клиенты службы Azure из последних клиентских библиотек Azure для .NET для внедрения зависимостей в приложении .NET. Каждое современное приложение .NET запускается с помощью инструкций, приведенных в файле Program.cs .
Установка пакетов
Чтобы зарегистрировать и настроить клиенты служб из Azure.
префиксированного пакета:
Установите пакет Microsoft.Extensions.Azure в проекте:
dotnet add package Microsoft.Extensions.Azure
Установите пакет Azure.Identity, чтобы настроить
TokenCredential
тип для проверки подлинности всех зарегистрированных клиентов, которые принимают такой тип:dotnet add package Azure.Identity
В демонстрационных целях пример кода в этой статье использует библиотеки Key Vault Secret, BLOB-объектов, служебная шина и Azure OpenAI. Установите следующие пакеты, чтобы выполнить следующие действия:
dotnet add package Azure.Security.KeyVault.Secrets
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Messaging.ServiceBus
dotnet add package Azure.AI.OpenAI
Регистрация клиентов и подклиентов
Клиент службы — это точка входа в API для службы Azure— из нее пользователи библиотеки могут вызывать все операции, которые предоставляет служба и легко реализовать наиболее распространенные сценарии. Где это упрощает проектирование API, группы вызовов служб можно упорядочить вокруг небольших подклиентных типов. Например, ServiceBusClient
можно зарегистрировать дополнительные ServiceBusSender
подклиенты для публикации сообщений или ServiceBusReceiver
подклиентов для использования сообщений.
В файле Program.cs вызовите AddAzureClients метод расширения для регистрации клиента для каждой службы. В следующих примерах кода приводятся рекомендации по построителям приложений из Microsoft.AspNetCore.Builder
пространств имен и Microsoft.Extensions.Hosting
пространств имен.
using Azure.Identity;
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;
using Azure.AI.OpenAI;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddAzureClients(async clientBuilder =>
{
// Register clients for each service
clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace(
"<your_namespace>.servicebus.windows.net");
// Set a credential for all clients to use by default
DefaultAzureCredential credential = new();
clientBuilder.UseCredential(credential);
// Register a subclient for each Service Bus Queue
List<string> queueNames = await GetQueueNames(credential);
foreach (string queue in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
(_, _, provider) => provider.GetService<ServiceBusClient>()
.CreateSender(queue)).WithName(queue);
}
// Register a custom client factory
clientBuilder.AddClient<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});
WebApplication app = builder.Build();
async Task<List<string>> GetQueueNames(DefaultAzureCredential credential)
{
// Query the available queues for the Service Bus namespace.
var adminClient = new ServiceBusAdministrationClient
("<your_namespace>.servicebus.windows.net", credential);
var queueNames = new List<string>();
// Because the result is async, the queue names need to be captured
// to a standard list to avoid async calls when registering. Failure to
// do so results in an error with the services collection.
await foreach (QueueProperties queue in adminClient.GetQueuesAsync())
{
queueNames.Add(queue.Name);
}
return queueNames;
}
В предыдущем коде:
- Секреты Key Vault, хранилище BLOB-объектов и служебная шина клиенты регистрируются с помощью AddSecretClientAddBlobServiceClient и AddServiceBusClientWithNamespaceсоответственно. Передаются
Uri
аргументы - иstring
типизированные. Чтобы избежать явного указания этих URL-адресов, ознакомьтесь с конфигурацией Магазина отдельно от раздела кода . - DefaultAzureCredential используется для удовлетворения требования аргумента
TokenCredential
для каждого зарегистрированного клиента. При созданииDefaultAzureCredential
одного из клиентов используется для проверки подлинности. - служебная шина подклиенты регистрируются для каждой очереди в службе с помощью подклиента и соответствующих типов параметров. Имена очередей для подклиентов извлекаются с помощью отдельного метода вне регистрации службы, так как
GetQueuesAsync
метод должен выполняться асинхронно. - Клиент Azure OpenAI регистрируется с помощью настраиваемой фабрики клиентов с помощью AddClient метода, который обеспечивает контроль над созданием экземпляра клиента. Пользовательские клиентские фабрики полезны в следующих случаях:
- Во время построения клиента необходимо использовать другие зависимости.
- Метод расширения регистрации не существует для клиента службы, который требуется зарегистрировать.
Использование зарегистрированных клиентов
Зарегистрированные клиенты, как описано в разделе "Регистрация клиентов и подклиентов ", теперь можно использовать их. В следующем примере внедрение конструктора используется для получения клиента хранилища BLOB-объектов и фабрики для подклиентов отправителя служебная шина в контроллере API ядра ASP.NET:
[ApiController]
[Route("[controller]")]
public class MyApiController : ControllerBase
{
private readonly BlobServiceClient _blobServiceClient;
private readonly ServiceBusSender _serviceBusSender;
public MyApiController(
BlobServiceClient blobServiceClient,
IAzureClientFactory<ServiceBusSender> senderFactory)
{
_blobServiceClient = blobServiceClient;
_serviceBusSender = senderFactory.CreateClient("myQueueName");
}
[HttpGet]
public async Task<IEnumerable<string>> Get()
{
BlobContainerClient containerClient =
_blobServiceClient.GetBlobContainerClient("demo");
var results = new List<string>();
await foreach (BlobItem blob in containerClient.GetBlobsAsync())
{
results.Add(blob.Name);
}
return results.ToArray();
}
}
Хранение конфигурации отдельно от кода
В разделе "Регистрация клиентов и подклиентов" вы явно передали Uri
типизированные переменные конструкторам клиента. Такой подход может вызвать проблемы при выполнении кода в различных средах при разработке и в работе. Команда разработчиков .NET предлагает хранить такие конфигурации в отдельных JSON-файлах для соответствующих сред. Например, в файле appsettings.Development.js можно хранить параметры среды разработки. В другом файле, appsettings.Production.js, храните параметры рабочей среды и т. д. У файлов должен быть следующий формат.
{
"AzureDefaults": {
"Diagnostics": {
"IsTelemetryDisabled": false,
"IsLoggingContentEnabled": true
},
"Retry": {
"MaxRetries": 3,
"Mode": "Exponential"
}
},
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net"
},
"ServiceBus": {
"Namespace": "<your_namespace>.servicebus.windows.net"
},
"Storage": {
"ServiceUri": "https://mydemoaccount.storage.windows.net"
}
}
В JSON-файл можно добавить любые свойства из ClientOptions класса. Параметры в файле конфигурации JSON можно получить с помощью IConfiguration.
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddSecretClient(
builder.Configuration.GetSection("KeyVault"));
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("Storage"));
clientBuilder.AddServiceBusClientWithNamespace(
builder.Configuration["ServiceBus:Namespace"]);
clientBuilder.UseCredential(new DefaultAzureCredential());
// Set up any default settings
clientBuilder.ConfigureDefaults(
builder.Configuration.GetSection("AzureDefaults"));
});
В предыдущем примере JSON:
- Имена ключей верхнего уровня,
AzureDefaults
,KeyVault
иServiceBus
, иStorage
, являются произвольными. Все остальные имена ключей содержат значение, а сериализация JSON выполняется без учета регистра. - Литерал
AzureDefaults.Retry
объекта:- Представляет параметры конфигурации политики повторных попыток.
- Соответствует свойству Retry. В этом литерале объекта вы найдете
MaxRetries
ключ, соответствующий свойству MaxRetries .
- Значения
KeyVault:VaultUri
,ServiceBus:Namespace
иStorage:ServiceUri
ключевые значения сопоставляются сUri
аргументами - иstring
типизированными аргументами перегрузки Azure.Security.KeyVault.Secrets.SecretClient.SecretClient(Uri, TokenCredential, SecretClientOptions)Azure.Messaging.ServiceBus.ServiceBusClient.ServiceBusClient(String)конструктора, соответственноAzure.Storage.Blobs.BlobServiceClient.BlobServiceClient(Uri, TokenCredential, BlobClientOptions). ВариантыTokenCredential
конструкторов используются, так как значение по умолчаниюTokenCredential
устанавливается с помощью Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential(TokenCredential) вызова метода.
Настройка разных имен для нескольких клиентов служб
Представьте, что у вас есть две учетные записи хранения: одна для частной информации и другая для общедоступной информации. Приложение передает данные из общедоступной учетной записи хранения в частную учетную запись хранения после некоторой операции. Необходимо два клиента служб хранения. Чтобы отличить эти два клиента, используйте WithName метод расширения:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PublicStorage"));
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PrivateStorage"))
.WithName("PrivateStorage");
});
С помощью контроллера ASP.NET Core в качестве примера можно получить доступ к именованный клиент службы с помощью IAzureClientFactory<TClient> интерфейса:
public class HomeController : Controller
{
private readonly BlobServiceClient _publicStorage;
private readonly BlobServiceClient _privateStorage;
public HomeController(
BlobServiceClient defaultClient,
IAzureClientFactory<BlobServiceClient> clientFactory)
{
_publicStorage = defaultClient;
_privateStorage = clientFactory.CreateClient("PrivateStorage");
}
}
Неименованные клиенты служб будут доступны, как и прежде. Именованные клиенты аддитивны.
Настройка новой политики повтора
В какой-то момент может потребоваться изменить параметры по умолчанию для клиента службы. Например, могут потребоваться разные параметры повторных попыток или использовать другую версию API службы. Вы можете задавать параметры повтора глобально или же отдельно для каждой службы. Предположим, что в проекте ASP.NET Core есть следующий файл appsettings.json :
{
"AzureDefaults": {
"Retry": {
"maxRetries": 3
}
},
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net"
},
"ServiceBus": {
"Namespace": "<your_namespace>.servicebus.windows.net"
},
"Storage": {
"ServiceUri": "https://store1.storage.windows.net"
},
"CustomStorage": {
"ServiceUri": "https://store2.storage.windows.net"
}
}
Вы можете изменить политику повторных попыток в соответствии с вашими потребностями следующим образом:
builder.Services.AddAzureClients(clientBuilder =>
{
// Establish the global defaults
clientBuilder.ConfigureDefaults(
builder.Configuration.GetSection("AzureDefaults"));
clientBuilder.UseCredential(new DefaultAzureCredential());
// A Key Vault Secrets client using the global defaults
clientBuilder.AddSecretClient(
builder.Configuration.GetSection("KeyVault"));
// A Blob Storage client with a custom retry policy
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("Storage"))
.ConfigureOptions(options => options.Retry.MaxRetries = 10);
clientBuilder.AddServiceBusClientWithNamespace(
builder.Configuration["ServiceBus:Namespace"])
.ConfigureOptions(options => options.RetryOptions.MaxRetries = 10);
// A named storage client with a different custom retry policy
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("CustomStorage"))
.WithName("CustomStorage")
.ConfigureOptions(options =>
{
options.Retry.Mode = Azure.Core.RetryMode.Exponential;
options.Retry.MaxRetries = 5;
options.Retry.MaxDelay = TimeSpan.FromSeconds(120);
});
});
Вы также можете поместить переопределения политики повторных попыток в файл appsettings.json :
{
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net",
"Retry": {
"maxRetries": 10
}
}
}