JavaScript 配置服务提供者

配置提供者 npm 包

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

加载配置

load 包中导出的 @azure/app-configuration-provider 方法可用于从 Azure 应用程序配置加载配置。 利用 load 方法,可以使用 Microsoft Entra ID 或连接字符串连接到应用程序配置存储区。

可以使用 DefaultAzureCredential 向应用程序配置存储区进行身份验证。 按照说明为凭据分配应用程序配置数据读取者角色。

const { load } = require("@azure/app-configuration-provider");
const { DefaultAzureCredential } = require("@azure/identity");
const endpoint = process.env.AZURE_APPCONFIG_ENDPOINT;
const credential = new DefaultAzureCredential(); // For more information, see https://learn.microsoft.com/azure/developer/javascript/sdk/credential-chains#use-defaultazurecredential-for-flexibility

async function run() {
    // Connect to Azure App Configuration using a token credential and load all key-values with no label.
    const appConfig = await load(endpoint, credential);
    console.log('appConfig.get("message"):', appConfig.get("message"));
}

run();

load 方法会返回一个 AzureAppConfiguration 类型的实例,该实例定义如下:

type AzureAppConfiguration = {
    refresh(): Promise<void>;
    onRefresh(listener: () => any, thisArg?: any): Disposable;
} & IGettable & ReadonlyMap<string, any> & IConfigurationObject;

有关 refreshonRefresh 方法的详细信息,请参阅配置刷新部分。

使用配置

AzureAppConfiguration 类型扩展了以下接口:

  • IGettable

    interface IGettable {
        get<T>(key: string): T | undefined;
    }
    

    IGettable 接口提供了 get 方法,用于从 Map 样式的数据结构中检索键值的值。

    const appConfig = await load(endpoint, credential);
    const fontSize = appConfig.get("app:font:size"); // value of the key "app:font:size" from the App Configuration store
    
  • ReadonlyMap

    AzureAppConfiguration 类型还扩展了 ReadonlyMap 接口,提供对键值对的只读访问权限。

  • IConfigurationObject

    interface IConfigurationObject {
        constructConfigurationObject(options?: ConfigurationObjectConstructionOptions): Record<string, any>;
    }
    

    IConfigurationObject 接口提供了 constructConfigurationObject 方法,用于基于 Map 样式的数据结构和分层键构造配置对象。 ConfigurationObjectConstructionOptions 参数是一个可选参数,可用于指定将分层键转换为对象属性的分隔符。 默认情况下,分隔符为 "."

    interface ConfigurationObjectConstructionOptions {
        separator?: "." | "," | ";" | "-" | "_" | "__" | "/" | ":"; // supported separators
    }
    

    在 JavaScript 中,通常使用对象或映射作为表示配置的主要数据结构。 JavaScript 配置提供程序库支持这两种配置方法,使开发人员能够灵活选择最适合其需求的选项。

    const appConfig = await load(endpoint, credential);
    const settingsObj = appConfig.constructConfigurationObject({separator: ":"});
    const fontSize1 = appConfig.get("app:font:size"); // map-style configuration representation
    const fontSize2 = settingsObj.app.font.size; // object-style configuration representation
    

JSON 内容类型处理

可以在应用配置 中创建 JSON 键值 。 从 Azure 应用配置加载键值时,配置提供程序会自动将有效 JSON 内容类型(例如 application/json)的键值转换为对象。

{
    "key": "font",
    "label": null,
    "value": "{\r\n\t\"size\": 12,\r\n\t\"color\": \"red\"\r\n}",
    "content_type": "application/json"
}

上述键值将加载为 { size: 12, color: "red" }

const appConfig = await load(endpoint, credential);
const { size, color } = appConfig.get("font");

使用选择器加载特定键值

默认情况下,load 方法将从配置存储区中加载所有没有标签的配置。 可以通过 load 类型的可选参数来配置 AzureAppConfigurationOptions 方法的行为。

若要优化或扩展从应用程序配置存储区加载的配置,可以在 AzureAppConfigurationOptions.selectors 属性下指定键选择器或标签选择器。

const appConfig = await load(endpoint, credential, {
    selectors: [
        { // load the subset of keys starting with "app1." prefix and "test" label
            keyFilter: "app1.*",
            labelFilter: "test"
        },
        { // load the subset of keys starting with "dev" label"
            labelFilter: "dev*"
        }
    ]
});

注意

键值会按选择器列出的顺序加载。 如果多个选择器检索到具有相同键的键值,则最后一个选择器的值将替代之前加载的值。

从键中剪裁前缀

可以通过向 AzureAppConfigurationOptions.trimKeyPrefixes 属性提供经过剪裁的键前缀列表来剪裁键前缀。

const appConfig = await load(endpoint, credential, {
    selectors: [{
        keyFilter: "app.*"
    }],
    trimKeyPrefixes: ["app."]
});

配置刷新

动态刷新配置可以从应用程序配置存储区拉取其最新值,而无需重启应用程序。 可以设置 AzureAppConfigurationOptions.refreshOptions 以启用刷新并配置刷新选项。 当服务器上检测到所选键值发生更改时,将更新加载的配置。 默认使用 30 秒刷新间隔,但你可以使用 refreshIntervalInMs 属性重写此间隔。

const appConfig = await load(endpoint, credential, {
    refreshOptions: {
        enabled: true,
        refreshIntervalInMs: 15_000
    }
});

仅仅是设置 refreshOptions 不会自动刷新配置。 需要调用由 refresh 方法返回的 AzureAppConfiguration 实例上的 load 方法,以触发刷新。

// this call is not blocking, the configuration will be updated asynchronously
appConfig.refresh();

此设计可防止应用程序处于空闲状态时对应用程序配置发出不必要的请求。 应在应用程序活动发生的位置包含 refresh 调用。 这称为活动驱动的配置刷新。 例如,可以在处理传入请求时或在执行复杂任务的迭代中调用 refresh

const server = express();
// Use an express middleware to refresh configuration whenever a request comes in
server.use((req, res, next) => {
    appConfig.refresh();
    next();
})

即使刷新调用因任何原因而失败,应用程序也将继续使用缓存的配置。 当配置的刷新间隔已过,并且应用程序活动触发刷新调用时,将再次尝试。 在配置的刷新间隔过去之前调用 refresh 是一个空操作,因此,即使频繁调用,它的性能影响也很小。

自定义刷新回叫

使用 onRefresh 方法可以自定义回叫函数,每次本地配置成功与 Azure 应用程序配置存储区的更改同步更新时,都会调用这些函数。 它返回一个可释放对象,可用于删除已注册的回叫

const appConfig = await load(endpoint, credential, {
    refreshOptions: {
        enabled: true
    }
});
const disposer = appConfig.onRefresh(() => {
    console.log("Config refreshed.");
});

appConfig.refresh();
// Once the refresh is successful, the callback function you registered will be executed.
// In this example, the message "Config refreshed" will be printed.

disposer.dispose();

刷新 Sentinel 键

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

const appConfig = await load(endpoint, credential, {
    refreshOptions: {
        enabled: true,
        watchedSettings: [
            { key: "sentinel" }
        ]
    }
});

有关刷新配置的详细信息,请转到在 JavaScript 中使用动态配置

功能标志

可以在 Azure 应用程序配置中创建功能标志。 默认情况下,配置提供程序不会加载功能标志。 调用 AzureAppConfigurationOptions.featureFlagOptions 方法时,可以通过 load 属性启用加载和刷新功能标志。

const appConfig = await load(endpoint, credential, {
    featureFlagOptions: {
        enabled: true, // enable loading feature flags
        selectors: [ { keyFilter: "*", labelFilter: "Prod" } ],
        refresh: {
            enabled: true, // enable refreshing feature flags
            refreshIntervalInMs: 60_000
        }
    }
});

注意

如果 featureFlagOptions 已启用且未指定选择器,则配置提供程序将从应用程序配置存储区加载所有无标签的功能标志。

重要

若要有效地使用和管理从 Azure 应用配置加载的功能标志,请安装和使用该 @microsoft/feature-management 包。 此库提供了一种结构化方法来控制应用程序中的功能行为。

特征管理

功能管理库提供了基于功能标志开发和公开应用程序功能的方法。 功能管理库旨在与配置提供程序库结合使用。 配置提供程序会将所有选定的功能标志加载到 feature_flags 部分 feature_management 列表下的配置中。 功能管理库将使用并管理为应用程序加载的功能标志。

以下示例演示如何将 @microsoft/feature-management 库与配置提供程序集成,以根据功能开关的状态动态控制 Express 应用程序中的 API 访问。

// Load feature flags from Azure App Configuration
import { load } from "@azure/app-configuration-provider";
const appConfig = await load(endpoint, credential, {
    featureFlagOptions: {
        enabled: true, // enable loading feature flags
        refresh: {
            enabled: true // enable refreshing feature flags
        }
    }
});

import { ConfigurationMapFeatureFlagProvider, FeatureManager } from "@microsoft/feature-management";
// Create a feature flag provider which uses the configuration provider as feature flag source
const ffProvider = new ConfigurationMapFeatureFlagProvider(appConfig);
// Create a feature manager which will evaluate the feature flag
const fm = new FeatureManager(ffProvider);

import express from "express";
const server = express();

// Use a middleware to achieve request-driven configuration refresh
server.use((req, res, next) => {
    // this call is not blocking, the configuration will be updated asynchronously
    appConfig.refresh();
    next();
});

server.get("/Beta", async (req, res) => {
    if (await featureManager.isEnabled("Beta")) {
        res.send("Welcome to the Beta page!");
    } else {
        res.status(404).send("Page not found");
    }
});

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

Key Vault 引用

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

配置提供程序库可检索 Key Vault 引用,就如同检索存储在应用程序配置中的任何其他密钥一样。 由于客户端可将密钥识别为 Key Vault 引用,因此它们具有唯一的 content-type,客户端将连接到 Key Vault,为应用程序检索它们的值。 需要使用正确的凭据配置 AzureAppConfigurationOptions.KeyVaultOptions 属性,以便配置提供程序可以连接到 Azure Key Vault。

const credential = new DefaultAzureCredential();
const appConfig = await load(endpoint, credential, {
    keyVaultOptions: {
        credential: credential
    }
});

还可以直接向 SecretClient 提供 KeyVaultOptions 实例。 这样,就可以在创建 SecretClient 时自定义选项。

import { SecretClient } from "@azure/keyvault-secrets";

const credential = new DefaultAzureCredential();
const secretClient = new SecretClient(keyVaultUrl, credential, {
    serviceVersion: "7.0",
});
const appConfig = await load(endpoint, credential, {
    keyVaultOptions: {
        secretClients: [ secretClient ]
    }
});

也可以设置 secretResolver 属性,以便本地解析没有与 Key Vault 关联的机密。

const resolveSecret = (url) => "From Secret Resolver";
const appConfig = await load(endpoint, credential, {
    keyVaultOptions: {
        secretResolver: resolveSecret
    }
});

你还可以设置 clientOptions 属性来配置 SecretClientOptions,用于连接到没有注册 SecretClient 的 Azure 密钥保管库。

const credential = new DefaultAzureCredential();
const appConfig = await load(endpoint, credential, {
    keyVaultOptions: {
        credential: credential,
        clientOptions: { // configure a custom SecretClientOptions
            retryOptions: { 
                maxRetries: 3, 
                maxRetryDelayInMs: 1000 
            }
        }
    }
});

并行机密解析

Azure Key Vault 不提供用于在单个请求中检索多个机密的批处理 API。 当应用程序需要加载大量密钥保管库引用时,可以通过使用 KeyVaultOptions 中的 parallelSecretResolutionEnabled 属性启用并行机密解析来提高性能。 这允许提供程序并行提取多个机密,而不是按顺序提取:

const credential = new DefaultAzureCredential();
const appConfig = await load(endpoint, credential, {
    keyVaultOptions: {
        credential: credential,
        parallelSecretResolutionEnabled: true
    }
});

注意

并行解析机密时,可能会遇到 Azure Key Vault 的服务限制 。 为了有效处理限制,请通过为 SecretClient 配置适当的重试选项来实现客户端限制最佳做法。 可以注册自定义 SecretClient 实例,也可以通过 AzureAppConfigurationOptions.keyVaultOptions 配置 clientOptions

快照

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

可以使用快照选择器从快照加载键值或功能标志:

const appConfig = await load(endpoint, credential, {
    selectors: [
        { snapshotName: "MySnapshot" }, // load key-values from snapshot
        { keyFilter: "test*", labelFilter: "test" }
    ],
    featureFlagOptions: {
        enabled: true,
        selectors: [
            { snapshotName: "MySnapshot" }, // load feature flags from snapshot
            { keyFilter: "*", labelFilter: "test" }
        ]
    }
});

启动重试

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

可以通过以下方法 AzureAppConfigurationOptions.startupOptions自定义此行为:

const appConfig = await load(endpoint, credential, { 
    startupOptions: { 
        timeoutInMs: 300_000
    }
});

异地复制

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

后续步骤

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

若要了解如何使用 JavaScript 功能管理库,请继续阅读以下文档。