Injeksi dependensi dengan Azure SDK untuk .NET
Artikel ini menunjukkan cara mendaftarkan klien layanan Azure dari pustaka klien Azure terbaru untuk .NET untuk injeksi dependensi di aplikasi .NET. Setiap aplikasi .NET modern dimulai dengan menggunakan instruksi yang disediakan dalam file Program.cs .
Memasang paket
Untuk mendaftarkan dan mengonfigurasi klien layanan dari Azure.
paket -prefiks:
Instal paket Microsoft.Extensions.Azure di proyek Anda:
dotnet add package Microsoft.Extensions.Azure
Instal paket Azure.Identity untuk mengonfigurasi jenis yang
TokenCredential
akan digunakan untuk mengautentikasi semua klien terdaftar yang menerima jenis seperti itu:dotnet add package Azure.Identity
Untuk tujuan demonstrasi, kode sampel dalam artikel ini menggunakan pustaka Rahasia Key Vault, Blob Storage, Bus Layanan, dan Azure OpenAI. Instal paket berikut untuk diikuti:
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
Mendaftarkan klien dan subkelas
Klien layanan adalah titik masuk ke API untuk layanan Azure - dari itu, pengguna pustaka dapat memanggil semua operasi yang disediakan layanan dan dapat dengan mudah menerapkan skenario yang paling umum. Di mana ia akan menyederhanakan desain API, grup panggilan layanan dapat diatur di sekitar jenis subkelas yang lebih kecil. Misalnya, ServiceBusClient
dapat mendaftarkan subkelas tambahan ServiceBusSender
untuk menerbitkan pesan atau ServiceBusReceiver
subkelas untuk menggunakan pesan.
Dalam file Program.cs, panggil AddAzureClients metode ekstensi untuk mendaftarkan klien untuk setiap layanan. Sampel kode berikut memberikan panduan tentang penyusun aplikasi dari Microsoft.AspNetCore.Builder
namespace layanan dan 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;
}
Dalam kode sebelumnya:
- Rahasia Key Vault, Blob Storage, dan klien Bus Layanan didaftarkan menggunakan AddSecretClient, AddBlobServiceClient dan AddServiceBusClientWithNamespace, masing-masing. Argumen
Uri
- danstring
-typed diteruskan. Untuk menghindari menentukan URL ini secara eksplisit, lihat bagian Simpan konfigurasi secara terpisah dari kode . - DefaultAzureCredential digunakan untuk memenuhi
TokenCredential
persyaratan argumen untuk setiap klien terdaftar. Ketika salah satu klien dibuat,DefaultAzureCredential
digunakan untuk mengautentikasi. - Bus Layanan subkelas didaftarkan untuk setiap antrean pada layanan menggunakan jenis opsi subkelas dan yang sesuai. Nama antrean untuk subkelas diambil menggunakan metode terpisah di luar pendaftaran layanan karena
GetQueuesAsync
metode harus dijalankan secara asinkron. - Klien Azure OpenAI terdaftar menggunakan pabrik klien kustom melalui AddClient metode , yang memberikan kontrol atas cara instans klien dibuat. Pabrik klien kustom berguna dalam kasus berikut:
- Anda perlu menggunakan dependensi lain selama konstruksi klien.
- Metode ekstensi pendaftaran tidak ada untuk klien layanan yang ingin Anda daftarkan.
Menggunakan klien terdaftar
Dengan klien yang terdaftar, seperti yang dijelaskan di bagian Daftarkan klien dan subkelas , Anda sekarang dapat menggunakannya. Dalam contoh berikut, injeksi konstruktor digunakan untuk mendapatkan klien Blob Storage dan pabrik untuk subkelas pengirim Bus Layanan dalam pengontrol API Inti 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();
}
}
Menyimpan konfigurasi secara terpisah dari kode
Di bagian Daftarkan klien dan subkelas , Anda secara eksplisit meneruskan Uri
variabel -typed ke konstruktor klien. Pendekatan ini dapat menyebabkan masalah ketika Anda menjalankan kode terhadap lingkungan yang berbeda selama pengembangan dan produksi. Tim .NET menyarankan penyimpanan konfigurasi tersebut dalam file JSON yang bergantung pada lingkungan. Misalnya, Anda dapat memiliki appsetting . Development.json file yang berisi pengaturan lingkungan pengembangan. Appsetting lain. Production.json file akan berisi pengaturan lingkungan produksi, dan sebagainya. Format file adalah:
{
"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"
}
}
Anda dapat menambahkan properti apa pun dari ClientOptions kelas ke dalam file JSON. Pengaturan dalam file konfigurasi JSON dapat diambil menggunakan 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"));
});
Dalam sampel JSON sebelumnya:
- Nama kunci tingkat atas,
AzureDefaults
, ,KeyVault
ServiceBus
, danStorage
, segan-segan. Semua nama kunci lainnya memiliki signifikansi, dan serialisasi JSON dilakukan dengan cara yang tidak peka huruf besar/kecil. - Objek
AzureDefaults.Retry
harfiah:- Mewakili pengaturan konfigurasi kebijakan coba lagi.
- Retry Sesuai dengan properti . Dalam objek tersebut secara harfiah, Anda menemukan
MaxRetries
kunci, yang sesuai dengan MaxRetries properti .
- Nilai
KeyVault:VaultUri
kunci ,ServiceBus:Namespace
, danStorage:ServiceUri
dipetakan keUri
argumen - danstring
-typed dari Azure.Security.KeyVault.Secrets.SecretClient.SecretClient(Uri, TokenCredential, SecretClientOptions)konstruktor , Azure.Messaging.ServiceBus.ServiceBusClient.ServiceBusClient(String), dan Azure.Storage.Blobs.BlobServiceClient.BlobServiceClient(Uri, TokenCredential, BlobClientOptions) kelebihan beban, masing-masing.TokenCredential
Varian konstruktor digunakan karena defaultTokenCredential
diatur melalui Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential(TokenCredential) panggilan metode.
Mengonfigurasi beberapa klien layanan dengan nama yang berbeda
Bayangkan Anda memiliki dua akun penyimpanan: satu untuk informasi privat dan satu lagi untuk informasi publik. Aplikasi Anda mentransfer data dari publik ke akun penyimpanan privat setelah beberapa operasi. Anda harus memiliki dua klien layanan penyimpanan. Untuk membedakan kedua klien tersebut WithName , gunakan metode ekstensi:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PublicStorage"));
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PrivateStorage"))
.WithName("PrivateStorage");
});
Menggunakan pengontrol ASP.NET Core sebagai contoh, akses klien layanan bernama menggunakan IAzureClientFactory<TClient> antarmuka:
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");
}
}
Klien layanan yang tidak disebutkan namanya masih tersedia dengan cara yang sama seperti sebelumnya. Klien bernama bersifat aditif.
Mengonfigurasi kebijakan coba lagi baru
Pada titik tertentu, Anda mungkin ingin mengubah pengaturan default untuk klien layanan. Misalnya, Anda mungkin menginginkan pengaturan coba lagi yang berbeda atau menggunakan versi API layanan yang berbeda. Anda dapat mengatur pengaturan coba lagi secara global atau per layanan. Asumsikan Anda memiliki file appsettings.json berikut dalam proyek ASP.NET Core Anda:
{
"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"
}
}
Anda dapat mengubah kebijakan coba lagi agar sesuai dengan kebutuhan Anda seperti:
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);
});
});
Anda juga dapat menempatkan penimpaan kebijakan coba lagi dalam file appsettings.json :
{
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net",
"Retry": {
"maxRetries": 10
}
}
}