特性标志

提示

此内容摘自电子书《为 Azure 构建云原生 .NET 应用程序》,可在 .NET 文档上获取,也可作为免费可下载的 PDF 脱机阅读。

Cloud Native .NET apps for Azure eBook cover thumbnail.

在第 1 章中,我们断定云原生主要是关于速度和敏捷性的。 用户希望快速响应、创新工作和零故障时间。 Feature flags是一种新式部署技术,有助于提高云原生应用程序的敏捷性。 通过它们,你可将新功能部署到生产环境中,但限制其可用性。 只需轻按开关,你就可为特定用户激活一项新功能,而无需重启应用或部署新代码。 它们将新功能的发布与代码部署分开。

功能标志建立在条件逻辑之上,该逻辑在运行时控制用户功能的可见性。 在现代云原生系统中,通常会尽早将新功能部署到生产环境中,但对有限的受众测试它们。 随着置信度的增加,可以增量方式向更广泛的受众推出此功能。

功能标志的其他用例包括:

  • 将高级功能限制给愿意支付更高的订阅费用的特定客户组。
  • 通过快速停用问题功能来稳定系统,避免回滚或即时修补程序的风险。
  • 在高峰使用期间,禁用资源占用率高的可选功能。
  • 向一小撮用户执行experimental feature releases来验证可行性和普及程度。

功能标志还可促进trunk-based开发。 这是一种源代码控制分支模型;在该模型中,开发人员协作处理单个分支中的功能。 此方法可最大程度地降低合并大量长时间运行的功能分支的风险和复杂性。 功能在激活前不可用。

实现功能标志

功能标志的核心是对简单 decision object 的引用。 它会返回布尔状态 onoff。 标志通常包装一个代码块,后者封装一个特征功能。 标志的状态确定是否对给定用户执行代码块。 图 10-11 显示了该实现。

if (featureFlag) {
    // Run this code block if the featureFlag value is true
} else {
    // Run this code block if the featureFlag value is false
}

图 10-11 -简单的功能标志实现。

请注意这种方法是如何将决策逻辑与功能代码分来的。

在第 1 章中,我们讨论了Twelve-Factor App。 该指南建议在应用程序可执行代码的外部保留配置设置。 如果需要,可从外部源中读取这些设置。 功能标志配置值还应独立于其代码库。 通过在单独的存储库中将标记配置外部化,无需修改和重新部署应用程序即可更改标记状态。

Azure 应用程序配置提供功能标志的集中存储库。 借助它,你可定义不同种类的功能标志,并快速、自信地操作其状态。 要启用“功能标志”功能,需要将应用程序配置客户端库添加到应用程序中。 支持各种编程语言框架。

可在 ASP.NET Core 服务中轻松实现功能标志。 安装 .NET 功能管理库和应用程序配置提供程序后,可以声明方式向代码添加功能标志。 它们启用 FeatureGate 属性,这样就无需在代码库中手动编写 if 语句。

在 Startup 类中配置后,可在控制器、操作或中间件级别添加功能标志功能。 图 10-12 显示了控制器和操作实现:

[FeatureGate(MyFeatureFlags.FeatureA)]
public class ProductController : Controller
{
    ...
}
[FeatureGate(MyFeatureFlags.FeatureA)]
public IActionResult UpdateProductStatus()
{
    return ObjectResult(ProductDto);
}

图 10-12 -控制器和操作中的功能标志实现。

如果功能标志被禁用,则用户将收到 404(找不到)状态代码,并且没有响应正文。

功能标志还可直接注入 C# 类中。 图 10-13 显示了功能标志注入:

public class ProductController : Controller
{
    private readonly IFeatureManager _featureManager;

    public ProductController(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }
}

图 10-13 -将功能标志注入到类中。

功能管理库在后台管理功能标志生命周期。 例如,若要最大程度地减少对配置存储的大量调用,这些库会将标记状态缓存指定的持续时间。 它们可保证在请求调用期间,标记状态保持不变。 它们还提供Point-in-time snapshot。 可重新构造任何键/值的历史记录,并提供过去 7 天内任何时间的值。