3

微软Azure配置中心 App Configuration (二):Feature Flag 功能开关特性 - 乔达摩(嘿...

 1 year ago
source link: https://www.cnblogs.com/xiaxiaolu/p/16611542.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

2、注入服务(net6)#

builder.Services.AddFeatureManagement();

3、配置文件写几个配置#

appsettings.json

   "FeatureManagement": { 
    //简单功能开关
    "Beta": true,
    "v1": true,
    "v2": true,
  }

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

  public enum MyFeatureFlags
    {
        Beta,
        V1,
        V2,
        PercentageFlag,
        TimeWindowFlag,
        CustomFeatureFlag
    }

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

4、使用功能开关#

1、创建一个FeatureFlagController;

注入服务:

private readonly IFeatureManager _featureManager;

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

简单功能开关:#

/// <summary>
/// 当启用beta版本的时候接口有效
/// </summary>
/// <returns></returns>
[FeatureGate(MyFeatureFlags.Beta)]
[HttpGet]
public async Task<IActionResult> Beta()
{
    var beta = await _featureManager.IsEnabledAsync(nameof(MyFeatureFlags.Beta));
    if (beta)
    {
      //beta版本特有逻辑
    }
    return Success("Beta", beta); //这里Success是封装的,大家可以改成返回Ok()
}

/// <summary>
/// 当启用v1版本的时候接口有效
/// </summary>
/// <returns></returns>
[FeatureGate(MyFeatureFlags.V1)]
[HttpGet]
public async Task<IActionResult> V1()
{
    return Success("V1");
}

/// <summary>
/// 当启用v2版本的时候接口有效
/// </summary>
/// <returns></returns>
[FeatureGate(MyFeatureFlags.V2)]
[HttpGet]
public async Task<IActionResult> V2()
{
    return Success("V2");
}

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

...
//简单功能开关
"Beta": true,
"v1": true,
"v2": true,

可以看到:

image-20220804104253051

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

image-20220804104401620

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

基于过滤器的功能开关:#

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

a、百分率功能开关
/// <summary>
/// 启用百分率的功能开关
/// </summary>
/// <returns></returns>
[FeatureGate(MyFeatureFlags.PercentageFlag)]
[HttpGet]
public async Task<IActionResult> PercentageFlag()
{
    return Success("PercentageFlag");
}
builder.Services.AddFeatureManagement()
    .AddFeatureFilter<PercentageFilter>();

添加配置:

FeatureManagement节点下:

//百分率功能开关
"PercentageFlag": {
  "EnabledFor": [
    {
      "Name": "Percentage",
      "Parameters": {
        "Value": 30
      }
    }
  ]
},

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

image-20220804105858780

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

b、时间窗口功能开关
/// <summary>
/// 启用时间窗口的功能开关
/// </summary>
/// <returns></returns>
[FeatureGate(MyFeatureFlags.TimeWindowFlag)]
[HttpGet]
public async Task<IActionResult> TimeWindowFlag()
{
    return Success("TimeWindowFlag");
}
builder.Services.AddFeatureManagement()
    .AddFeatureFilter<TimeWindowFilter>();

添加配置:

//时间窗口功能开关
"TimeWindowFlag": {
  "EnabledFor": [
    {
      "Name": "TimeWindow",
      "Parameters": {
        "Start": "2022/08/03 08:00:00 +00:00", //这里是UTC时间
        "End": "2022/08/03 09:00:00 +00:00"
      }
    }
  ]
},

这个开关在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<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
    {
    	//这里参数模拟平台,实际业务会有实际业务的逻辑
        var platform = _httpContextAccessor.HttpContext.Request.Query["platform"].ToString();
        var allowPlatform = context.Parameters.Get<CustomFeatureFilterSettings>();
        return Task.FromResult(allowPlatform.AllowedPlatforms.Any(c => c == platform));
    }
}

public class CustomFeatureFilterSettings
{
    public string[] AllowedPlatforms { get; set; }
}
/// <summary>
/// 自定义功能开关
/// </summary>
/// <returns></returns>
[FeatureGate(MyFeatureFlags.CustomFeatureFlag)]
[HttpGet]
public async Task<IActionResult> CustomFeatureFlag(string platform)
{
    return Success("CustomFeatureFlag");
}
builder.Services.AddFeatureManagement()
    .AddFeatureFilter<CustomFeatureFilter>();

添加配置:

//自定义功能开关
"CustomFeatureFlag": {
  "EnabledFor": [
    {
      "Name": "CustomFeature",
      "Parameters": {
        "AllowedPlatforms": [ //这里配置运行启用功能的平台
          "phone",
          "pad"
          //"pc"
        ]
      }
    }
  ]
}

我们来测测:

image-20220804111012239

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

集成Azure配置中心App Configuration方式#

1、添加配置:#

  "ConnectionStrings": {
    "AppConfig": "<your app connection string>"
  },

具体可参考我之前的文章:《微软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)
                });
    });
});

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

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

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

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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK