.Net Core功能开关实战


为了快速发布开发完成的功能,企业通常会以比较快的迭代周期持续发布。但是由于某些 原因或场景,需要在发布的时候将某些功能隐藏起来或者小规模的开放(例如只有某些特定用户可以使用、或者特定日期开放),通过使用功能开关(feature toggle\feature flag)可以很好的解决这个问题,接下来小编将以.net core为例给大家介绍此功能的具体实现。


640?wx_fmt=jpeg


作者:周文洋

leansoftX.com研发总监,认证 ScrumMaster,曾为多家客户提供微软Team Foundation Server实施咨询、二次开发、报表定制等服务,包括:中国农业银行,博时基金,斯伦贝谢,京东商城,国电南自等,现负责公司核心产品的开发工作。


Feature Toggle介绍


Feature Flag (又名 Feature Toggle、Feature switch、Flip等) 是一种可以通过配置(配置文件、数据库等)或自动化(特定用户、特定时间等)控制线上功能开启或者关闭的方式。核心思想就是将功能的开发和代码的发布解耦。


发布功能开关:

通过发布功能开关,开发团队可以将未完成的功能在发布时设置为隐藏,这样就可以持续的发布新功能到生产也不会影响到用户的使用,同时避免了一个复杂功能需要较长开发周期导致的在合并代码的时候出现各种冲突难以解决的问题。直到新功能稳定,开启功能开关或者删除对应功能开关来完成功能上线。


业务功能开关:

- 实现A/B测试。

- 针对特定人群发布功能尽早获得反馈。

- 针对特定条件开启或者关闭功能。例如可以在特定时间、特定地域、特定人员开启,能线上开启或者关闭,实现快速回滚。


.Net Core实战


开源框架:


网上有很多相关的开源框架,例如(NFeature、FeatureSwitcher、nToggle、Feature Toggle等),这里小编使用了Jason Roberts提供的: 开源Feature Toggle框架 


https://github.com/jason-roberts/FeatureToggle


原因是,安装简单、支持不同的.net 平台,默认提供了很多Toggle Provider可以直接使用,而且拓展方便。


支持的.NET平台:


- Net Desktop/Server Applications

- Windows Store Apps && Windows Phone Silverlight Apps


已提供的Toggle:


- AlwaysOffFeatureToggle(Hardcode功能默认为关闭,如果需要更改必须重新编译程序)

- AlwaysOnFeatureToggle(Hardcode功能默认为开启,如果需要更改必须重新编译程序)

- SimpleFeatureToggle(通过配置文件开启或关闭相应功能web.confg\app.xaml\appsetting.json)

- EnabledOnOrAfterDateFeatureToggle(在特定日期开启功能)

- EnabledOnOrBeforeDateFeatureToggle(在特定日期开启功能)

- EnabledBetweenDatesFeatureToggle(在特定日期内功能开启)

- EnabledOnDaysOfWeekFeatureToggle (在一周的特定日期开启功能,比如周末 )

- RandomFeatureToggle (自动随机的开机或关闭某个功能)

- SqlFeatureToggle (通过读取数据库完成开关配置)


Feature Toggle配置:


这里小编将选取几个比较有代表性的Toggle来演示具体实现,比如RandomFeatureToggle、SimpleFeatureToggle,其他的大家可以自己研究下。


以及演示如何创建自定义”功能SpecificUsersFeatureToggle”并应用。


DEMO源码

https://github.com/leansoftX/FeatureToggleDemo


安装Feature Toggle包:


点击 管理Nuget程序包 | 搜索Feature Toggle | 选择包 | 点击安装

640?wx_fmt=png


Demo1 – 随机开启或关闭功能:


本实例将演示如何通过继承 RandomFeatureToggle 类,实现功能的随机开机或关闭。


例如这里小编实现了随机显示或隐藏当前程序中“微信通知”功能。


1.  添加功能类 – WechatNotifyFeature.cs, 如下图所示


640?wx_fmt=png

640?wx_fmt=png


2. 选择需要使用的 Toggle Provider,在WechatNotifyFeature类中,添加引用:FeatureToggle;  并继承类: RandomFeatureToggle,代码如下:

using FeatureToggle;  
namespace LeansoftX_FeatureToggle.Models.FeatureToggles { public class WechatNotifyFeature:RandomFeatureToggle { } }


3. 添加HomeViewModel,并添加功能开关属性,获取功能开关值(返回 True or False)

using FeatureToggle; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 
using LeansoftX_FeatureToggle.Models.FeatureToggles; 
namespace LeansoftX_FeatureToggle.Models 
{ public class HomeViewModel { 
        public WechatNotifyFeature WechatNotifyFeature { get { return new WechatNotifyFeature(); } } }
}


4. 修改Home控制器,代码如下

public IActionResult Index() 
{ 
    return View (new Models.HomeIndexViewModel()); 
}


5. 修改视图,代码如下:

@model LeansoftX_FeatureToggle.Models.HomeIndexViewModel 
@if (Model.WechatNotifyFeature.FeatureEnabled) 
{ 
    <li><a asp-area="" asp-controller="Home" asp-action="About">微信通知</a></li> 
}


6. 启动应用效果如下(微信通知菜单随机显示或隐藏):


640?wx_fmt=png

点击 管理Nuget程序包 | 搜索Feature Toggle | 选择

Demo2 – 通过配置文件控制功能开关


通常我们更希望的是通过配置文件来决定某个功能是否需要开启,这里可以通过继承 SimpleFeatureToggle 类加配置文件的方式实现功能的开启或关闭。


这里小编实现了配置“邮件通知”功能的显示或隐藏。


1. 添加功能类: EmailNotifyFeature.cs , 如下图所示:


640?wx_fmt=png

640?wx_fmt=png


2. 在EmailNotifyFeature类中,添加引用FeatureToggle.  并继承SimpleFeatureToggle.

using FeatureToggle;
using System;
using System.Collections.Generic;
using System.Linq;using System.Threading.Tasks;
namespace LeansoftX_FeatureToggle.Models.FeatureToggles {   
   public class EmailNotifyFeature: SimpleFeatureToggle   
{   
} }


3. 修改Startup.cs,在ConfigureServices方法中添加如下代码,设置功能开关使用Appsetting.json配置文件作为Provider:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FeatureToggle.Internal;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using LeansoftX_FeatureToggle.Models.FeatureToggles;
namespace LeansoftX_FeatureToggle {
    public class Startup
    {
        public IConfigurationRoot Configuration { get; }
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                          .SetBasePath(env.ContentRootPath)
                          .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                          .AddJsonFile($"appsettings.{env.EnvironmentName}
                         .json", optional: true)
                          .AddEnvironmentVariables();
            Configuration = builder.Build();
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var provider = new AppSettingsProvider { Configuration = Configuration };
            services.AddSingleton(new EmailNotifyFeature { ToggleValueProvider = provider });
            services.AddMvc();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    } }


4. 修改配置文件Appsetting.json,添加FeatureToggle节点,并配置EmailNotifyFeature功能开启或者关闭。

{
  "FeatureToggle": {
    "EmailNotifyFeature": "true" 
 },
 
"Logging": {
"IncludeScopes": false,
"LogLevel": {
                   "Default": "Debug",     
                   "System": "Information",     
                   "Microsoft": "Information"   
}
} }


5. 修改HomeContoller,代码如下:

private readonly EmailNotifyFeature _emailNotifyFeature;
public HomeController(EmailNotifyFeature emailNotifyFeature) {_emailNotifyFeature = emailNotifyFeature; }
public IActionResult Index() {ViewBag.EmailNotifyFeature = _emailNotifyFeature;return View(new Models.HomeIndexViewModel()); }


6. 修改视图代码如下

@model LeansoftX_FeatureToggle.Models.HomeIndexViewModel 
@{ 
     var emailNotifyFeature = 
    (LeansoftX_FeatureToggle.Models.FeatureToggles.EmailNotifyFeature)ViewBag.EmailNotifyFeature;
    ViewData["Title"]= "LeansoftX"; Layout = null;
} <div class="navbar-collapse collapse"><ul class="nav navbar-nav"><li><a asp-area="" asp-controller="Home" asp-action="Index">主页</a></li> @if (Model.WechatNotifyFeature.FeatureEnabled) { <li><a asp-area="" asp-controller="Home" asp-action="About">微信通知</a></li> }        @if (emailNotifyFeature.FeatureEnabled)
       {
           <li>
           <a asp-area="" asp-controller="Home" asp-action="Email">
               邮件通知
           </a>
           </li>
        }
</ul> </div>


7. 开启功能,效果如下:


640?wx_fmt=png


8. 关闭功能,效果如下:


640?wx_fmt=png


Demo3 – 自定义功能开关


现有的 ”开关” 往往不能满足我们的实际需求,我们可以继承IFeatureToggle接口实现自定义的 ”开关”, 这里小编实现了“短信通知”功能只对特定用户开放。


1. 添加自定义开关 SpecificUsersFeatureToggle,添加引用 FeatureToggle; 继承并实现接口 IFeatureToggle,代码如下: 继承自此类的“功能”只针对用户”jackyzhou”或者”leixu”开放。

注意:这里代码逻辑是随机返回一个用户,具体实现请下载Github实例代码查看。 大家可以根据实际需求改为读取“数据库特定权限用户”或者“付费用户”等其他方式。

public class SpecificUsersFeatureToggle : IFeatureToggle{
   public bool FeatureEnabled {
       get {
               var user = new Models.Users().GetUser();                if (user.Name == "jackyzhou" || user.Name == "leixu"){
                   return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }

}


2. 添加功能类 – SMSNotifyFeature


640?wx_fmt=png


3. 在 SMSNotifyFeature 类中,添加引用:FeatureToggle 并继承类 SpecificUsersFeatureToggle 代码如下:

public class SMSNotifyFeature:CustomToggles.SpecificUsersFeatureToggle    
{    
}


4. 在View Model中添加属性,如下代码:

public class HomeIndexViewModel 
{ public WechatNotifyFeature WechatNotifyFeature { get { return new WechatNotifyFeature(); } 
    public SMSNotifyFeature SMSNotifyFeature
   {
       get { return new SMSNotifyFeature(); }
   }
}


5. 修改视图,代码如下:

@if (Model.WechatNotifyFeature.FeatureEnabled) 
{ <li><a asp-area="" asp-controller="Home" asp-action="About">微信通知</a></li> 
} 
@if (emailNotifyFeature.FeatureEnabled) 
{ <li><a asp-area="" asp-controller="Home" asp-action="Email">邮件通知</a></li> 
} 
@if (Model.SMSNotifyFeature.FeatureEnabled)
{
    <li>
       <a asp-area="" asp-controller="Home" asp-action="SMS">短信通知</a>
   </li>
}


6. 设置断点,并启动应用,效果如下(当前用户为user02, 所以短信功能不可见):


640?wx_fmt=png


7. 设置断点,并启动应用,效果如下(当前用户为leixu, 所以短信功能为可见):


640?wx_fmt=png

总结


通过FeatureToggle可以持续的将新功能发布到生产环境,并通过开关灵活控制每个功能显示与隐藏,可以是特定环境开关、特定时间开关、特定地域开关、或者特定人员开关。可以帮助我们实现A/B测试,线上小规模测试。

通过FeautreToggle可以持续的将未完成的功能合并到主干分支,并对用户隐藏,避免了一个复杂功能需要较长开发周期导致的在合并代码的时候出现各种冲突,难以合并或者影响其他功能的正常使用。


另外小编在本章中只是demo了如何对前端逻辑实现功能隐藏,实际应用过程中也需要对业务逻辑进行控制。


END


原文地址: https://devopshub.cn/2018/10/08/dotnetcore-featuretoggle/


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319562.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AtCoder Beginner Contest 179 总结

A - Plural Form 模拟签到题1 #define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<string> #include<iostream> #include<algorithm> using namespace std; const int N100010; int main() {IO;int T1;//cin…

纪中A组模拟赛总结(2021.7.19)

成绩 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3101010lyflyflyf175175175000757575100100100 前言&#xff1a;进前10啦&#xff01;&#xff01; 总结 T1看着推了一下&#xff0c;发现可以改变答案的解决顺序&#xff0c;然后在O(n)内求解&#xff0c;打完…

AT4505-[AGC029F]Construction of a tree【构造题,hall定理,网络流】

正题 题目链接:https://www.luogu.com.cn/problem/AT4505 题目大意 给出nnn个点和n−1n-1n−1个点集UiU_iUi​&#xff0c;每个点集中选择两个点连边使得该图是一棵树。求方案。 n∈[1,105],∑i1n−1∣Ui∣∈[1,2∗105]n\in[1,10^5],\sum_{i1}^{n-1} |U_i|\in[1,2*10^5]n∈[1…

学习究竟是为了什么?

今天无意中看到一句话&#xff0c;人如果停止了学习&#xff0c;就开始走向失败。这句话其实应该送给每一个面临30岁焦虑期的开发者&#xff0c;同时也应该成为每一个开发者内心的真实写照。 想问一下大家一个问题&#xff0c;多久没有学习新的知识呢&#xff1f;尤其…

Codeforces Round #671 (Div. 2)

当天晚上&#xff0c;本来想参加一下比赛&#xff0c;结果感觉静不下心来做题&#xff0c;而且最难受的是读个题都不明白&#xff0c;一直在理解题意。 A - Digit Game 分析不难发现&#xff1a; 如果nnn是奇数&#xff0c;那么最后留下的数字一定是奇数位上的数字&#xff0…

【网络流】人员雇佣(luogu 1791)

正题 luogu 1791 题目大意 有n个人&#xff0c;选择第i个人的代价是aia_iai​&#xff0c;如果i,j同时被选那么有贡献wi,jw_{i,j}wi,j​&#xff0c;如果i选了j没选那么有贡献−wi,j-w_{i,j}−wi,j​&#xff0c;问你最大贡献&#xff08;减去代价&#xff09; 解题思路 最大…

AT4144-[ARC098D]Donation【Kruskal重构树,dp】

正题 题目链接:https://www.luogu.com.cn/problem/AT4144 题目大意 nnn个点mmm条边的一张无向联通图&#xff0c;每个点有两个值ai,bia_i,b_iai​,bi​。表示经过该点时需要拥有aia_iai​元&#xff0c;该点需要捐献bib_ibi​元。 任意起点&#xff0c;询问开始时至少多少钱才…

Strategic game

来源&#xff1a;牛客网&#xff1a; 时间限制&#xff1a;C/C 2秒&#xff0c;其他语言4秒 空间限制&#xff1a;C/C 10000K&#xff0c;其他语言20000K 64bit IO Format: %lld题目描述 Bob enjoys playing computer games, especially strategic games, but sometimes he c…

ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(一)

上个月15日&#xff0c;上海MVP做了一次线下的技术分享活动&#xff0c;我分享的主题是《快速构建容器化的ASP.NET Core应用程序》&#xff0c;有关这次活动的简报&#xff0c;可以参考这里。另外&#xff0c;我的主题分享的PPT也可以点击这里下载。由于线下活动时间紧迫&#…

牛客练习赛 63 F-牛牛的树行棋

F-牛牛的树行棋 大佬题解 对于每一个棋子来说&#xff0c;都是独立的&#xff0c;因此当前局面的 SG 值就是每一枚棋子的 SG 值的异或和。若一枚棋子的往子树内最多可以走 kkk 步&#xff0c;它的 SG 值为 kkk。然后就可以dfs求出整个局面的SG值。 仔细再思考一步&#xff1a…

【DP】小学生语文题(jzoj 5102)

正题 jzoj 5102 题目大意 给你两个串A,B&#xff0c;字母个数相等&#xff0c;可以把B的一个字符移到前面某个位置&#xff0c;问你最少移多少次可以使A,B相等 解题思路 设fi,jf_{i,j}fi,j​为A匹配了i-n&#xff0c;B用了j-n 1.当i,j匹配时fi,jfi1,j1f_{i,j}f_{i1,j1}fi,j…

AT3949-[AGC022D]Shopping【贪心】

正题 题目链接:https://www.luogu.com.cn/problem/AT3949 题目大意 长度为LLL的坐标轴上&#xff0c;给出nnn个点&#xff0c;每个点xix_ixi​需要购物tit_iti​的时间&#xff0c;一辆车在0∼L0\sim L0∼L折返跑&#xff0c;求从000出发购物完回到000的最短时间。 n∈[1,310…

现代软件工程的《构建之法》

要想了解世界&#xff0c;就必须亲自来打造它。—— 帕韦泽&#xff08;Cesare Pavese&#xff09;国庆假日期间&#xff0c;我重读了邹欣老师的《构建之法》一书。我从事软件行业相关工作超过15年&#xff0c;每每在被问到给在校计算机专业大学生的学习建议时&#xff0c;我都…

牛客练习赛 62

A.牛妹的游戏 Ramsey定理&#xff1a;人话解释任意六个人中要么至少三个人认识&#xff0c;要么至少三个不认识。 结论简要证明: 假设 666 个据点分别为 A,B,C,D,E,FA,B,C,D,E,FA,B,C,D,E,F那么在 A 连向其它据点的控制链中&#xff0c;必然至少有 333条链被同一方控制&#x…

【图论】【斜率优化】前往大都会(loj 2769)

正题 jzoj 7181 题目大意 给你由若干铁路组成的图&#xff08;一个铁路上有若干点&#xff09;&#xff0c;问你从1到n在最短路径的前提下&#xff0c;乘坐的每一条铁路所花费时间的平方和的最大值 解题思路 先用dij跑出最短路图&#xff08;即长度等于最短路的所有路径&…

AT4995-[AGC034E] Complete Compress【树形dp】

正题 题目链接:https://www.luogu.com.cn/problem/AT4995 题目大意 nnn个点的一棵树&#xff0c;上面有一些棋子&#xff0c;每次可以选择两个棋子移动到他们之间的路径上相邻的点上&#xff0c;求最少多少步能移动到一个点上。 n∈[1,2000]n\in[1,2000]n∈[1,2000] 解题思路 …

【每日一题】8月10日题目精讲—排座椅

来源&#xff1a;牛客网&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 51200K&#xff0c;其他语言102400K 64bit IO Format: %lld题目描述 上课的时候总有一些同学和前后左右的人交头接耳&#xff0c;这是令小学班主任十分头疼的…

使用Consul做服务发现的若干姿势

从2016年起就开始接触Consul&#xff0c;使用的主要目的就是做服务发现&#xff0c;后来逐步应用于生产环境&#xff0c;并总结了少许使用经验。最开始使用Consul的人不多&#xff0c;为了方便交流创建了一个QQ群&#xff0c;这两年微服务越来越火&#xff0c;使用Consul的人也…

【费用流】【线性规划】志愿者招募(luogu 3980)

正题 luogu 3980 题目大意 有n个时刻&#xff0c;第i个时刻需要aia_iai​个志愿者&#xff0c;有m类志愿者&#xff0c;第j类可以从ljl_jlj​做到rjr_jrj​&#xff0c;代价为wjw_jwj​&#xff0c;数量无限&#xff0c;问你使所有时刻志愿者个数都足够的最小代价 解题思路 …

YbtOJ#643-机器决斗【贪心,李超树】

正题 题目链接:https://www.ybtoj.com.cn/problem/643 题目大意 nnn个机器人&#xff0c;第iii个攻击力为AiA_iAi​&#xff0c;防御为DiD_iDi​。 然后你每次可以对一个机器人造成AtkAtkAtk点伤害&#xff0c;之后所有机器人对你进行一次攻击。 开局可以删除两个机器人&…