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 功能管理库的详细信息,请转到功能标志快速入门

密钥保管库引用

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

配置提供程序库可检索 Key Vault 引用,就如同检索存储在应用程序配置中的任何其他密钥一样。 由于客户端可将密钥识别为 Key Vault 引用,因此它们具有独特的内容类型,客户端将连接到 Key Vault,为您的应用程序检索其值。 需要使用正确的凭据配置 AzureAppConfigurationOptions.KeyVaultOptions 属性,以便配置提供程序连接到由世纪互联运营的 Azure 密钥保管库。

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 属性设置为本地解析未与密钥库关联的机密。

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

异地复制

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

后续步骤

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

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