• 微软Azure配置中心 App Configuration (二):Feature Flag 功能开关特性


    🚀 优质资源分享 🚀

    学习路线指引(点击解锁)知识定位人群定位
    🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
    💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

    img

    写在前面

    Web服务开发过程中我们经常有这样的需求:

    • 某些功能我必须我修改了配置才启用,比如新用户注册送券等;
    • 某个功能需到特定的时间才启用,过后就失效,比如春节活动等;
    • 某些功能,我想先对10%的用户开放,验证没问题后再逐步全量开放等;

    这就是功能开关。

    日常开发中功能开关我们一般是写到配置文件里的,根据不同的配置,做不同的逻辑;但,其实.net core是对功能开关有官方支持的,但因为跟Azure集成比较好所以文档不在.net core的文档里面,而是在Azure的文档这边:

    https://docs.microsoft.com/en-us/azure/azure-app-configuration/

    Asp.net Core中集成

    Asp.net Core的功能开关(Feature Flag)是直接仅根据配置文件方式使用,和集成Azure配置中心使用的;我们来看看区别;

    本地配置文件方式

    1、先安装包

    install-package Microsoft.FeatureManagement.AspNetCore
    
    
    • 1
    • 2

    2、注入服务(net6)

    builder.Services.AddFeatureManagement();
    
    
    • 1
    • 2

    3、配置文件写几个配置

    appsettings.json

       "FeatureManagement": { 
        //简单功能开关
        "Beta": true,
        "v1": true,
        "v2": true,
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    以上配置对应以下的枚举:

      public enum MyFeatureFlags
        {
            Beta,
            V1,
            V2,
            PercentageFlag,
            TimeWindowFlag,
            CustomFeatureFlag
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其实不用枚举,直接用字符串也是可以的;

    4、使用功能开关

    1、创建一个FeatureFlagController;

    注入服务:

    private readonly IFeatureManager _featureManager;
    
    public FeatureFlagController(IFeatureManager featureManager)
    {
         _featureManager = featureManager;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    简单功能开关:

    /// 
    /// 当启用beta版本的时候接口有效
    /// 
    /// 
    [FeatureGate(MyFeatureFlags.Beta)]
    [HttpGet]
    public async Task Beta()
    {
        var beta = await _featureManager.IsEnabledAsync(nameof(MyFeatureFlags.Beta));
        if (beta)
        {
          //beta版本特有逻辑
        }
        return Success("Beta", beta); //这里Success是封装的,大家可以改成返回Ok()
    }
    
    /// 
    /// 当启用v1版本的时候接口有效
    /// 
    /// 
    [FeatureGate(MyFeatureFlags.V1)]
    [HttpGet]
    public async Task V1()
    {
        return Success("V1");
    }
    
    /// 
    /// 当启用v2版本的时候接口有效
    /// 
    /// 
    [FeatureGate(MyFeatureFlags.V2)]
    [HttpGet]
    public async Task V2()
    {
        return Success("V2");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    由于我们上面的配置都是开启的:

    ...
    //简单功能开关
    "Beta": true,
    "v1": true,
    "v2": true,
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到:

    image-20220804104253051

    接口都可以访问,我们把v1改成false试试:

    image-20220804104401620

    马上404了,这里清晰的看到,功能开关在多版本Api上线下某个版本时候确实方便;

    基于过滤器的功能开关:

    基于过滤器的功能开关是有一定逻辑的功能开关;

    a、百分率功能开关
    /// 
    /// 启用百分率的功能开关
    /// 
    /// 
    [FeatureGate(MyFeatureFlags.PercentageFlag)]
    [HttpGet]
    public async Task PercentageFlag()
    {
        return Success("PercentageFlag");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    builder.Services.AddFeatureManagement()
        .AddFeatureFilter();
    
    
    • 1
    • 2
    • 3

    添加配置:

    FeatureManagement节点下:

    //百分率功能开关
    "PercentageFlag": {
      "EnabledFor": [
        {
          "Name": "Percentage",
          "Parameters": {
            "Value": 30
          }
        }
      ]
    },
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里的配置参数值代表30%的概率启用次功能,我们试试:

    image-20220804105858780

    分别是不启用,和启用状态;

    b、时间窗口功能开关
    /// 
    /// 启用时间窗口的功能开关
    /// 
    /// 
    [FeatureGate(MyFeatureFlags.TimeWindowFlag)]
    [HttpGet]
    public async Task TimeWindowFlag()
    {
        return Success("TimeWindowFlag");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    builder.Services.AddFeatureManagement()
        .AddFeatureFilter();
    
    
    • 1
    • 2
    • 3

    添加配置:

    //时间窗口功能开关
    "TimeWindowFlag": {
      "EnabledFor": [
        {
          "Name": "TimeWindow",
          "Parameters": {
            "Start": "2022/08/03 08:00:00 +00:00", //这里是UTC时间
            "End": "2022/08/03 09:00:00 +00:00"
          }
        }
      ]
    },
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这个开关在2022年8月3日 下午16时(北京时间)和17时这个世界窗口内才启用;对应的:

    **Start:**就是生效时刻;

    **End:**失效时刻;

    c、自定义功能开关

    ok,以上都是系统内置的功能开关,我们来根据自己需求创建一个自定义的;

    **需求:**某个功能只有在客户端是手机或者平板的情况下启用,pc端不启用;

    创建一个自定义功能开关过滤器类CustomFeatureFilter

    [FilterAlias("CustomFeature")]
    public class CustomFeatureFilter : IFeatureFilter
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
    
        public CustomFeatureFilter(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }
    
        public Task EvaluateAsync(FeatureFilterEvaluationContext context)
        {
        	//这里参数模拟平台,实际业务会有实际业务的逻辑
            var platform = _httpContextAccessor.HttpContext.Request.Query["platform"].ToString();
            var allowPlatform = context.Parameters.Get();
     return Task.FromResult(allowPlatform.AllowedPlatforms.Any(c => c == platform));
     }
    }
    
    public class CustomFeatureFilterSettings
    {
     public string[] AllowedPlatforms { get; set; }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    /// 
    /// 自定义功能开关
    /// 
    /// 
    [FeatureGate(MyFeatureFlags.CustomFeatureFlag)]
    [HttpGet]
    public async Task CustomFeatureFlag(string platform)
    {
        return Success("CustomFeatureFlag");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    builder.Services.AddFeatureManagement()
        .AddFeatureFilter();
    
    
    • 1
    • 2
    • 3

    添加配置:

    //自定义功能开关
    "CustomFeatureFlag": {
      "EnabledFor": [
        {
          "Name": "CustomFeature",
          "Parameters": {
            "AllowedPlatforms": [ //这里配置运行启用功能的平台
              "phone",
              "pad"
              //"pc"
            ]
          }
        }
      ]
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    我们来测测:

    image-20220804111012239

    可以看到仅在设置运行的平台下启用,验证ok;

    集成Azure配置中心App Configuration方式

    1、添加配置:

      "ConnectionStrings": {
        "AppConfig": ""
      },
    
    
    • 1
    • 2
    • 3
    • 4

    具体可参考我之前的文章:《微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core》

    2、启用Azure功能开关:

    var connectionString = builder.Configuration.GetConnectionString("AppConfig");
    
    builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
    {
    
        //配置不同功能
        config.AddAzureAppConfiguration(options =>
        {
            启用功能开关特性
            options.Connect(connectionString)
                   //启用功能开关特性
                  .UseFeatureFlags(options =>
                    {
                        options.CacheExpirationInterval = TimeSpan.FromSeconds(30); //配置FeatureFlag缓存本地时间(默认就是30)
                    });
        });
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    UseFeatureFlags启用后,本地配置文件的方式失效;

    builder.Services.AddAzureAppConfiguration(); //注入服务
    
    
    • 1
    • 2

    3、在Azure 配置中心后台配置好功能开关(代替本地配置文件)

    基本功能开关配置

    创建配置:

    image-20220804115402160

    填写配置信息:

    image-20220804122451808

    OK,以上是基本的配置,配置好后可以直接在列表页面勾选启用配置与否:

    image-20220804123400869

    基于过滤器的开关配置

    百分率功能开关

    image-20220804123721457

    时间窗口功能开关

    image-20220804123801220

    这里的Start date,和Expiry date,就对应前面配置文件的Start,End;

    自定义功能开关

    image-20220804123835703

    这里的过滤器的**Name:**CustomFeature ,要跟代码标签 [FilterAlias("CustomFeature")]一致;

    **AllowedPlatforms:**也要跟代码里面的配置一致,[“phone”,“pad”]这个是数组的写法;

    总结

    1、启用集成到Azure的UseFeatureFlags后,本地配置文件的方式失效;

    2、Azure这套功能开关还是有可选之处的,我尤其喜欢其接口标签[FeatureGate];

    另外定义了的标准配置项,与Azure配置中心无缝集成,香。

    源码

    https://github.com/gebiWangshushu/Hei.Azure.Test

    [参考]

    https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview

    👇专注于后端和架构,欢迎扫码关注我的公众号👇

  • 相关阅读:
    中集集团飞瞳全球港口航运人工智能领军企业中集飞瞳,成熟港航人工智能AI为港口船公司大幅提效降本,新一代智慧港口智慧船公司解决方案
    这不妥妥拿捏——简单整一个 python GUI 小例子
    module ‘torch‘ has no attribute ‘_six‘问题解决
    安装RabbitMQ的各种问题(包括已注册成windows服务后,再次重新安装,删除服务重新注册遇到的问题)
    使用jxls excel模板填充生成Excel,多sheet页处理
    MySQL 基础知识(九)之视图
    Inno Setup 选择安装路径的问题
    /proc/meminfo参数说明
    下属比你聪明/专业,经验还比你丰富怎么办?
    Linux磁盘管理、储存空间
  • 原文地址:https://blog.csdn.net/u012804784/article/details/126495837