你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

.NET 配置提供程序

Microsoft.Extensions.Configuration.AzureAppConfiguration

Azure 应用配置是一项托管服务,可帮助开发人员轻松且安全地集中管理其应用程序配置。 .NET 配置提供程序库允许以托管方式从 Azure 应用配置存储加载配置。 此客户端库在用于 .NET 的 Azure SDK 的基础上添加了其他 功能

加载配置

Azure 应用配置 .NET 配置提供程序与 .NET 配置系统集成,可以轻松地从 Azure 应用配置存储加载配置值。 可以在应用程序启动期间添加提供程序,并将其与其他配置源一起使用。

若要使用 .NET 配置提供程序,请安装包:

dotnet add package Microsoft.Extensions.Configuration.AzureAppConfiguration

IConfigurationBuilder上调用AddAzureAppConfiguration扩展方法,以将 Azure 应用配置添加为应用程序的配置提供程序。

配置提供程序库实现组合 选项模式生成器模式 ,以提供一种干净的声明性方法来配置 AzureAppConfigurationOptions。 该方法 AddAzureAppConfiguration 接受委托 Action<AzureAppConfigurationOptions> 参数,该参数允许你通过 Fluent API 配置提供程序。

若要连接到 Azure 应用配置存储区,请在 AzureAppConfigurationOptions 实例上使用Connect方法,该方法返回相同的选项对象,以便进行方法链调用。

您可以使用 DefaultAzureCredential 或其他任何 令牌凭据实现,以对您的应用配置存储进行身份验证。 按照说明为凭据分配“应用程序配置数据读取者”角色。

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Azure.Identity;

var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(options =>
    {
        string endpoint = Environment.GetEnvironmentVariable("AppConfigurationEndpoint");
        options.Connect(new Uri(endpoint), new DefaultAzureCredential());
    });

var config = builder.Build();
Console.WriteLine(config["TestApp:Settings:Message"] ?? "Hello world!");

注释

在 ASP.NET Core 应用程序或后台服务中,可以在 builder.Configuration 上调用 AddAzureAppConfiguration

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddAzureAppConfiguration(options =>
    {
        string endpoint = Environment.GetEnvironmentVariable("Endpoint");
        options.Connect(new Uri(endpoint), new DefaultAzureCredential());
    });

使用配置

添加 Azure 应用配置提供程序后,可以通过多种方式访问配置值:

1. 直接访问

最简单的方法是直接从 IConfiguration 实例检索值:

// Directly get the configuration
string message = configuration["TestApp:Settings:Message"];

IConfigurationSection settingsSection = configuration.GetSection("TestApp:Settings");

2. 使用 IConfiguration 进行依赖项注入

在服务或控制器中,可以直接注入和使用 IConfiguration 接口:

public class WeatherService
{
    private readonly IConfiguration _configuration;

    public WeatherService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public Task<WeatherForecast> GetForecastAsync()
    {
        // Access configuration values directly from the injected instance
        string apiEndpoint = _configuration["TestApp:Weather:ApiEndpoint"];

        ...

        return Task.FromResult(new WeatherForecast());
    }
}

3.强类型配置的选项模式

// Define a strongly-typed settings class
public class Settings
{
    public string BackgroundColor { get; set; }
    public long FontSize { get; set; }
    public string FontColor { get; set; }
    public string Message { get; set; }
}

builder.Services.Configure<Settings>(builder.Configuration.GetSection("TestApp:Settings"));

有关 .NET 中的选项模式的详细信息,请转到 文档

JSON 内容类型处理

可以在应用配置中创建 JSON 键值。 读取内容类型为 "application/json" 的键值对时,配置提供程序会将其平展为 IConfiguration 内的单个设置。 有关详细信息,请转到 “使用内容类型”在应用配置中存储 JSON 键值

使用选择器加载特定键值

默认情况下,配置提供程序加载应用配置中没有标签的所有键值。 可以通过调用方法SelectAzureAppConfigurationOptions从应用程序配置存储区选择性地加载键值。

builder.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(endpoint), new DefaultAzureCredential())
        // Load configuration values with prefix "TestApp:" and no label
        .Select("App:Settings:*")
        // Load configuration values with prefix "TestApp:" and "Prod" label
        .Select("App:Settings:*", "Prod")
        // Load configuration values with prefix "TestApp:" and "Prod" label that have the tag "Group" with value "Contoso"
        .Select("App:Settings:*", "Prod", new[] { "Group=Contoso" })
});

该方法 Select 采用三个参数。 第一个参数是用于指定要加载哪些键的键筛选器,第二个参数是用于指定要加载哪些具有特定标签的键值的标签筛选器,第三个参数指定了一组标签筛选器,这些筛选器必须全部存在于一个键值上才能加载。

注释

当多个 Select 调用包括重叠键时,后续调用优先于早期调用。

关键筛选器

密钥筛选器参数确定要包括的配置键:

  • 完全匹配:使用特定字符串仅匹配与筛选器完全匹配的键。
  • 前缀匹配:在末尾添加星号(*)会创建前缀筛选器(例如, App:Settings:* 加载以“App:Settings::”开头的所有键)。
  • 多键选择:使用逗号(,)允许选择多个显式键(例如)。 Key1,Key2,Key3
  • 保留字符:星号 (*)、逗号 (,) 和反斜杠 (\) 字符是保留字符,在键名称中使用时必须使用反斜杠进行转义(例如,键筛选器 a\\b\,\*c* 将返回键以 a\b,*c 开头的所有键值对)。

注释

不能在同一次 Select 调用中将通配符前缀匹配与逗号分隔的筛选器组合在一起。 例如,不支持abc*,def,但可以用abc*def单独进行Select调用。

标签筛选器

标签筛选器参数选择具有特定标签的键值。 如果未指定,则使用内置 LabelFilter.Null

注释

标签筛选器不支持字符星号 (*) 和逗号 (,)。 反斜杠 (\) 字符是保留字符,必须用另一个反斜杠 (\) 来进行转义。

标签筛选器

标记筛选器参数选择具有特定标记的键值。 仅当键值包含筛选器中指定的所有标记和相应值时,才会加载键值。 若要为标记指定 null 值,可以使用内置 TagValue.Null 值。

注释

星号 (*)、逗号 (,) 和反斜杠 (\) 字符是保留字符,在标记筛选器中使用时必须使用反斜杠进行转义。

去除键中的前缀

加载具有特定前缀的配置值时,可以使用 TrimKeyPrefix 该方法从配置中的键中删除这些前缀。 这会在你的应用程序中创建更清晰的配置密钥,同时保持应用程序配置存储的有序性。

builder.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(endpoint), new DefaultAzureCredential())
        // Load configuration values with prefix "TestApp:" and trim the prefix
        .Select("TestApp:*")
        .TrimKeyPrefix("TestApp:");
});

例如,如果你的应用程序配置存储区包含名为 TestApp:Settings:Message 的键,它将可以在剪裁掉 TestApp: 前缀之后在应用程序中作为 Settings:Message 被访问。

配置设置映射

从 Azure 应用配置加载键值时,提供程序首先将其检索为 ConfigurationSetting 对象,然后再将它们添加到 .NET 配置系统。 Map API 使你可以在此管道期间转换这些设置,从而控制配置在应用程序中的显示方式。

该方法 Map 接受接收 ConfigurationSetting 对象的委托函数,允许修改它,并返回一个 ValueTask<ConfigurationSetting>。 这对于基于运行时条件的键名称转换或值格式设置特别有用。

以下示例演示如何使用 API 将 Map 双下划线 (__) 替换为配置键中的冒号 (:)。 当键需要在应用配置中使用备用字符时,此转换将保留 .NET 配置所需的分层结构:

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())
        .Map((setting) =>
        {
            // Transform keys from format "App__Settings__Message" to "App:Settings:Message"
            setting.Key = setting.Key.Replace("__", ":");
            
            return new ValueTask<ConfigurationSetting>(setting);
        });
});

小窍门

您的 Map 操作将应用于从应用配置中检索到的所有配置设置,因此请确保您的转换逻辑能正确处理所有可能的密钥格式。

配置刷新

配置刷新使应用程序能够从应用程序配置存储区拉取最新值,而无需重启。 可以调用 ConfigureRefresh 该方法来配置键值刷新。

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())
        // Load all keys that start with `TestApp:` and have no label
        .Select(keyFilter: "TestApp:*", labelFilter: LabelFilter.Null)
        .ConfigureRefresh(refreshOptions => {
            // Trigger full configuration refresh when any selected key changes.
            refreshOptions.RegisterAll()
            // Check for changes no more often than every 60 seconds
                .SetRefreshInterval(TimeSpan.FromSeconds(60));
        });
});

ConfigureRefresh 方法中,调用 RegisterAll 该方法以指示应用配置提供程序在检测到任何所选键值(以 TestApp 开头且没有标签)发生更改时重新加载配置。

可添加对 SetRefreshInterval 方法的调用以指定配置刷新之间的最短时间。 如果未设置,则默认刷新间隔为 30 秒。

触发刷新

若要触发刷新,需要调用 IConfigurationRefresherTryRefreshAsync 方法。 Azure 应用配置根据应用程序体系结构提供多种实现模式。

1. 依赖关系注入

对于使用依赖项注入(包括 ASP.NET 核心和后台服务)的应用程序,请注册刷新器服务:

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())            
           .ConfigureRefresh(refreshOptions =>
           {
                refreshOptions.RegisterAll()
                    .SetRefreshInterval(TimeSpan.FromSeconds(60));
           })
});

// Register refresher service with the DI container
builder.Services.AddAzureAppConfiguration();

builder.Services.AddAzureAppConfiguration()IConfigurationRefreshProvider 服务添加到 DI 容器,该容器允许你访问应用程序配置中所有 Azure 应用配置源的刷新程序。

ASP.NET Core 应用程序

对于 ASP.NET Core 应用程序,可以使用 Microsoft.Azure.AppConfiguration.AspNetCore 包通过内置中间件实现 请求驱动的配置刷新

dotnet add package Microsoft.Azure.AppConfiguration.AspNetCore

注册服务后,调用 UseAzureAppConfigurationAzureAppConfigurationRefreshMiddleware 添加到应用程序管道中,以自动刷新接收请求时的配置。

...

// Call the AddAzureAppConfiguration to add refresher service to the DI container
builder.Services.AddAzureAppConfiguration();

var app = builder.Build();

// Call the app.UseAzureAppConfiguration() method as early as appropriate in your request pipeline so another middleware doesn't skip it
app.UseAzureAppConfiguration();

// Continue with other middleware registration
app.UseRouting();
...

AzureAppConfigurationRefreshMiddleware 会在配置的刷新间隔自动检查配置更改。 此方法非常有效,因为它仅在满足这两个条件时刷新:收到 HTTP 请求并且刷新间隔已过。

后台服务

对于后台服务,可以注入 IConfigurationRefresherProvider 服务并手动刷新每个已注册的刷新器。

public class Worker : BackgroundService
{
    private readonly IConfiguration _configuration;
    private readonly IEnumerable<IConfigurationRefresher> _refreshers;

    public Worker(IConfiguration configuration, IConfigurationRefresherProvider refresherProvider)
    {
        _configuration = configuration;
        _refreshers = refresherProvider.Refreshers;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        foreach (IConfigurationRefresher refresher in _refreshers)
        {
            refresher.TryRefreshAsync();
        }

        ...
    }
}

2. 直接访问

对于不使用依赖项注入的应用程序,可以直接从选项获取刷新器:

IConfigurationRefresher refresher = null;
var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())            
           .ConfigureRefresh(refreshOptions =>
           {
               refreshOptions.RegisterAll();
           });

    // Store the refresher for later use
    refresher = options.GetRefresher();
});

IConfiguration config = builder.Build();

// Later in your code, trigger refresh when needed
if (refresher != null)
{
    await refresher.TryRefreshAsync()
}

Console.WriteLine(config["TestApp:Settings:Message"]);

注释

即使刷新调用因任何原因而失败,应用程序也会继续使用缓存的配置。 经过一段时间后,会根据应用活动再次尝试。 在配置的刷新间隔过去之前调用刷新是一个空操作,因此即使频繁调用刷新,其性能影响也很小。

刷新 Sentinel 键

Sentinel 键是完成所有其他键的更改后更新的键。 配置提供程序将监视 sentinel 键,而不是所有选定的键值对。 检测到更改时,应用会刷新所有配置值。

更新多个键值时,此方法非常有用。 只有在完成所有其他配置更改后才会更新 sentinel 密钥,可确保应用程序仅重新加载配置一次,从而保持一致性。

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())
        // Load all keys that start with `TestApp:` and have no label
        .Select(keyFilter: "TestApp:*", labelFilter: LabelFilter.Null)
        .ConfigureRefresh(refreshOptions => {
            // Trigger full configuration refresh only if the `SentinelKey` changes.
            refreshOptions.Register("SentinelKey", refreshAll: true);
        });
});

重要

键值对不会自动注册用于刷新监视。 必须显式调用ConfigureRefresh,然后使用RegisterAll方法(监视所有加载的密钥)或者Register方法(监视单个密钥)来注册密钥。

有关刷新配置的详细信息,请转到 教程:在 ASP.NET Core 应用中使用动态配置

功能标志

Azure 应用配置中的功能标志提供了一种新式方法来控制应用程序中的功能可用性。 与常规配置值不同,必须使用该方法显式加载 UseFeatureFlags 功能标志。 可以使用选择器配置 FeatureFlagOptions 以加载特定功能标志,并设置功能标志刷新间隔。

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())
        .UseFeatureFlags(featureFlagOptions => {
            // Load feature flags with prefix "TestApp:" and "dev" label
            featureFlagOptions.Select("TestApp:*", "dev")
            // Check for changes no more often than every 60 seconds
                .SetRefreshInterval(TimeSpan.FromSeconds(60));
        });
});

UseFeatureFlags 方法中,调用 Select 该方法以选择性地加载功能标志。 可以使用 键筛选器标签筛选器标记筛选器 选择要加载的功能标志。 Select如果未调用任何方法,UseFeatureFlags则默认加载不带标签的所有功能标志。

与键值对不同的是,功能标志会自动注册进行刷新,而无需显式 ConfigureRefresh 调用。 可以通过SetRefreshInterval方法指定特性标志刷新之间的最短时间。 默认刷新间隔为 30 秒。

功能管理

功能管理库提供了一种基于功能标志开发和公开应用程序功能的方法。 功能管理库旨在与配置提供程序库结合使用。 安装 Microsoft.FeatureManagement 包:

dotnet add package Microsoft.FeatureManagement

可以调用 AddFeatureManagement 在 DI 容器中注册 IVariantFeatureManager 和相关服务。 此注册通过依赖项注入使功能标志功能在整个应用程序中可用。

using Microsoft.FeatureManagement;

...

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential());
    // Use feature flags
    options.UseFeatureFlags();
});

// Register feature management services
builder.Services.AddFeatureManagement();

以下示例演示如何通过依赖项注入使用功能管理器服务:

public class WeatherForecastController : ControllerBase
{
    private readonly IFeatureManager _featureManager;

    public WeatherForecastController(IVariantFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }

    [HttpGet]
    public async Task<IActionResult> Get()
    {
        // Check if a feature flag is enabled
        if (await _featureManager.IsEnabledAsync("WeatherForecast"))
        {
            var forecast = GenerateWeatherForecast();
            return Ok(forecast);
        }
        
        return NotFound("Weather forecast feature is not available");
    }
}

有关如何使用功能管理库的详细信息,请转到 功能标志快速入门

密钥保管库引用

Azure 应用程序配置支持引用存储在 Azure Key Vault 中的机密。 在应用程序配置中,可以创建映射到 Key Vault 中存储的机密的密钥。 机密安全地存储在 Key Vault 中,但加载后可以像其他配置一样访问。

配置提供程序库可检索 Key Vault 引用,就如同检索存储在应用程序配置中的任何其他密钥一样。 由于客户端将密钥识别为 Key Vault 引用,它们具有唯一的内容类型,因此客户端连接到 Key Vault 以检索密钥的值供应用程序使用。

连接到 Key Vault

需要调用 ConfigureKeyVault 该方法来配置如何连接到 Key Vault。 Azure 应用配置提供程序提供了多种方式来对 Key Vault 机密进行身份验证和访问。

1.注册 SecretClient 实例

你可以注册指定的 SecretClient 实例,以便为关联密钥保管库中的机密解析密钥保管库引用。

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

...

var secretClient = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential());

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())  
        .ConfigureKeyVault(kv =>
        {
            // Register a SecretClient instance
            kv.Register(secretClient);
        });
});

2.使用凭据

你可以设置用于向未注册 SecretClient 的密钥保管库进行身份验证的凭据。

using Azure.Identity;

...

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())  
        .ConfigureKeyVault(kv =>
        {
            // Use DefaultAzureCredential to access all Key Vaults
            kv.SetCredential(new DefaultAzureCredential());
        });
});

3. 使用自定义机密解析器

还可以调用 SetSecretResolver 来添加自定义机密解析程序,该解析程序将在没有可用的注册 SecretClient 或提供的凭据无法向密钥保管库进行身份验证时使用。 此方法接受将 Key Vault URI 解析为机密值的委托函数。 以下示例演示如何使用机密解析程序从开发中的环境变量中检索机密,并在密钥保管库无法获取机密时使用回退值。

var secretClient = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential());

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())  
        .ConfigureKeyVault(kv =>
        {
            // Add a custom secret resolver function
            kv.SetSecretResolver(async (Uri secretUri) =>
            {                
                if (builder.Environment.IsDevelopment())
                {
                    return Environment.GetEnvironmentVariable("FALLBACK_SECRET_VALUE");
                }

                try 
                {
                    var secret = await secretClient.GetSecretAsync(secretName);
                    return secret.Value;
                }
                catch (Exception ex)
                {
                    logger.LogWarning($"Failed to retrieve secret from {secretUri}: {ex.Message}");
                    
                    return Environment.GetEnvironmentVariable("FALLBACK_SECRET_VALUE");
                }
            });
        });
});

注释

解析 Key Vault 引用时,提供程序将遵循以下顺序:

  1. 已注册 SecretClient 实例
  2. 默认凭据
  3. 自定义机密解析程序

重要

如果应用程序在没有正确配置密钥保管库的情况下加载包含密钥保管库引用的键值对,则会在启动时引发异常。 确保已正确配置 Key Vault 访问或机密解析程序。

小窍门

你可以使用自定义机密解析程序来处理密钥保管库引用意外添加到应用程序配置存储区的情况。 解析程序可以提供回退值、日志警告,或者正常处理缺少的凭据以访问密钥保管库,而不是引发异常。

密钥保管库机密刷新

Azure 应用配置使您可以在配置刷新周期之外独立配置机密刷新间隔。 这对安全性至关重要,因为虽然应用配置中的 Key Vault 引用 URI 保持不变,但 Key Vault 中的基础机密可能会作为安全做法的一部分轮换。

若要确保应用程序始终使用最新的机密值,请配置 SetSecretRefreshInterval 该方法。 这强制提供程序在以下情况下从 Key Vault 检索新的机密值:

  • 应用程序调用 IConfigurationRefresher.TryRefreshAsync
  • 密钥设定的刷新间隔时间已过

即使应用配置存储中未检测到任何更改,此机制也能正常工作,确保应用程序与轮换的机密保持同步。

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())
        .ConfigureKeyVault(kv =>
        {
            kv.SetCredential(new DefaultAzureCredential());

            // Option 1: Set refresh interval for specific secrets
            kv.SetSecretRefreshInterval("ApiKey", TimeSpan.FromHours(12)); 
            
            // Option 2: Set a global refresh interval for all secrets with no refresh interval specified
            kv.SetSecretRefreshInterval(TimeSpan.FromHours(24));
        })
        .ConfigureRefresh(refreshOptions => refreshOptions.RegisterAll());
});

有关如何使用 Key Vault 引用的详细信息,请转到 教程:在 ASP.NET Core 应用中使用 Key Vault 引用

快照

快照 是一个应用配置存储库中的命名且不可变的键值子集。 构成快照的键值是在创建期间通过使用键和标签筛选器选择的。 创建快照后,其中的键值将保证保持不变。

可以调用 SelectSnapshot 以从快照加载键值。

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential());
    // Select an existing snapshot by name. This adds all of the key-values and feature flags from the snapshot to this application's configuration.
    options.SelectSnapshot("SnapshotName");
});

有关使用快照的信息,请转到 “创建和使用快照”。

启动重试

配置加载是应用程序启动期间的关键操作。 为了确保可靠性,Azure 应用配置提供程序在初始配置加载期间实现可靠的重试机制。 这有助于保护应用程序免受暂时性网络问题的影响,否则可能会阻止成功启动。

可以使用以下方法自定义此行为 ConfigureStartupOptions

builder.Configuration.AddAzureAppConfiguration(options =>
{
    options.Connect(new Uri(appConfigEndpoint), new DefaultAzureCredential())
        .ConfigureStartupOptions(startupOptions =>
        {
            // Set the time-out for the initial configuration load
            startupOptions.Timeout = TimeSpan.FromSeconds(60);
        });
});

异地复制

有关使用异地复制的信息,请转到启用异地复制

分布式跟踪

Azure 应用配置 .NET 提供程序包括对分布式跟踪的内置支持,使你能够监视和排查应用程序中的配置作问题。 提供程序公开一个名为 "Microsoft.Extensions.Configuration.AzureAppConfiguration"ActivitySource,后者将启动 Activity 来执行加载配置和刷新配置等密钥操作。

以下示例演示如何配置 OpenTelemetry 以捕获和监视配置提供程序生成的分布式跟踪:

List<Activity> exportedActivities = new();
builder.Services.AddOpenTelemetry()
    .WithTracing(traceBuilder => {
        traceBuilder.AddSource(["Microsoft.Extensions.Configuration.AzureAppConfiguration"]);
            .AddInMemoryExporter(exportedActivities)
    });

有关 .NET 中的 OpenTelemetry 的详细信息,请参阅 OpenTelemetry .NET 文档

后续步骤

若要了解如何使用 .NET 配置提供程序,请继续学习以下教程。