写在前面

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、先安装包

  1. install-package Microsoft.FeatureManagement.AspNetCore

2、注入服务(net6)

  1. builder.Services.AddFeatureManagement();

3、配置文件写几个配置

appsettings.json

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

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

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

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

4、使用功能开关

1、创建一个FeatureFlagController;

注入服务:

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

简单功能开关:

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

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

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

可以看到:

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

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

基于过滤器的功能开关:

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

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

添加配置:

FeatureManagement节点下:

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

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

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

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

添加配置:

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

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

Start:就是生效时刻;

End:失效时刻;

c、自定义功能开关

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

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

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

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

添加配置:

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

我们来测测:

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

集成Azure配置中心App Configuration方式

1、添加配置:

  1. "ConnectionStrings": {
  2. "AppConfig": "<your app connection string>"
  3. },

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

2、启用Azure功能开关:

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

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

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

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

基本功能开关配置

创建配置:

填写配置信息:

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

基于过滤器的开关配置

百分率功能开关

时间窗口功能开关

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

自定义功能开关

这里的过滤器的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

微软Azure配置中心 App Configuration (二):Feature Flag 功能开关特性的更多相关文章

  1. 微软Azure配置中心 App Configuration (三):配置的动态更新

    写在前面 我在前文: <微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core>已经介绍了Asp.net Core怎么轻易的接入azure ...

  2. 微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core

    写在前面 在日常开发中,我这边比较熟悉的配置中心有,携程Apollo,阿里Nacos(配置中心,服务治理一体) 之前文章: Asp.Net Core与携程阿波罗(Apollo)的第一次亲密接触 总体来 ...

  3. 七、springcloud之配置中心Config(二)之高可用集群

    方案一:传统作法(不推荐) 服务端负载均衡 将所有的Config Server都指向同一个Git仓库,这样所有的配置内容就通过统一的共享文件系统来维护,而客户端在指定Config Server位置时, ...

  4. 微软Azure通知中心 (Azure Notification Hubs)

    Azure Notification Hubs 提供简单的方法从后台(azure或者on-promise)去发送通知在不同的平台上面(iOS, Android, Windows, Kindle, Ba ...

  5. 分布式配置中心介绍--Spring Cloud学习第六天(非原创)

    文章大纲 一.分布式配置中心是什么二.配置基本实现三.Spring Cloud Config服务端配置细节(一)四.Spring Cloud Config服务端配置细节(二)五.Spring Clou ...

  6. springcloud学习之路: (五) springcloud集成SpringCloudConfig分布式配置中心

    SpringCloud全家桶中的分布式配置中心SpringCloudConfig, 它使用git来管理配置文件, 在修改配置文件后只需要调用一个接口就可以让新配置生效, 非常方便. SpringClo ...

  7. 撸了一个简易的配置中心,顺带整合到了SpringCloud

    大家好,我是三友~~ 最近突然心血来潮(就是闲的)就想着撸一个简单的配置中心,顺便也照葫芦画瓢给整合到SpringCloud. 本文大纲 配置中心的概述 随着历史的车轮不断的前进,技术不断的进步,单体 ...

  8. 配置中心之Nacos简介,使用及Go简单集成

    简介 为什么需要配置中心 ​ 我们现在有一个项目, 使用Gin进行开发的, 配置文件我们知道是一个config.yaml的文件, 也知道这个配置文件在项目启动时会被加载到内存中使用; 考虑三种情况: ...

  9. 给你的 ASP.NET Core 程序插上 Feature Flag 的翅膀

    前言 我们知道,目前大多数应用程序在正式发布到生产环境之前都会经历多个不同的测试环境,通过让应用程序在多个不同的环境中运行来及时发现并解决问题,避免在线上发生不必要的损失.这是对于整个软件的发布流程来 ...

随机推荐

  1. JAVA面向对象之封装和调用

    一   面向对象 面向对象的三大特性   1 封装:概念:封装是把过程和数据私有化,打包封存起来,对数据访问只能通过指定的方式.简单的可以理解为你把钱存到银行里,银行专员首先要给你开一个账户,之后你的 ...

  2. 在Ubuntu系统下,可执行文件的表现形式

    在Windows系统下的可执行文件都带有.exe的后缀,而对于Linux系统下的可执行文件,则不会带有后缀,如下图 对于.txt文件,Ubuntu下也有相应的记事本程序打开,对于.xml,ubuntu ...

  3. jieba分词的功能和性能分析

    jieba分词问题导引 用户词典大小最大可以有多大 用户词典大小对速度的影响 有相同前缀和后缀的词汇如何区分 对比百度分词的API 问题一:词典大小 从源码大小分析,整个jieba分词的源码总容量为8 ...

  4. python简单处理验证码,三分钟,不能再多了

    序言 大家好鸭, 又是我小熊猫啦 我们在做采集数据的时候,过快或者访问频繁,或者一访问就给弹出验证码,然后就蚌珠了~今天就给大家来一个简单处理验证码的方法 环境模块 Python和pycharm如果还 ...

  5. 10.5 详解Android Studio项目结构

    Android项目的结构很复杂,并不像HTML项目,最简单的直接一个HTML文件就行了,相信学完上一节的同学就明白,哪怕是一个HelloWorld这样一个项目的文件可能都有几十个,所以我们需要搞清楚, ...

  6. Windows对拍系统

    有个东西可以帮助对拍,告诉你两个程序的输出哪不一样(但是无法得知错误位置,聊胜于无吧) 一.打开计算机  二.在上方输入$cmd$,摁下回车 三.弹出对话窗如下,输入$fc +$空格,输入两个需要比较 ...

  7. CF1132D Stressful Training

    题目链接 题目 见链接. 题解 方法一 知识点:贪心,优先队列,二分. 显然,这道题可以用二分答案做.check 函数可以用小根堆,让维持时间最小的先充电. 但是不优化这道题会炸.有两个关键优化:一个 ...

  8. 渗透测试(PenTest)基础指南

    什么是渗透测试? 渗透测试(Penetration Test,简称为 PenTest),是指通过尝试利用漏洞攻击来评估IT基础设施的安全性.这些漏洞可能存在于操作系统.服务和应用程序的缺陷.不当配置或 ...

  9. 教你使用CANN将照片一键转换成卡通风格

    摘要:这次是将AnimeGAN部署到Ascend 310,从而实现对自己想要图片的一键转换为我们想看到的卡通风格. 本文分享自华为云社区<[CANN训练营]CANN训练营_昇腾AI趣味应用实现A ...

  10. Techempower web框架性能测试第21轮结果发布--asp.net core继续前进

    废话不说,直接上结果: Round 21 results - TechEmpower Framework Benchmarks Techempower benchmark是包含范围最广泛的web框架性 ...