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

作者:周文洋

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 | 选择包 | 点击安装

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

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

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

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

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. 启动应用效果如下(微信通知菜单随机显示或隐藏):

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

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

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

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

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

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. 开启功能,效果如下:

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

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

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, 所以短信功能不可见):

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

总结

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

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

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

END

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


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

.Net Core功能开关实战相关推荐

  1. ASP.NET Core使用功能开关控制路由访问

    前言 在前面的文章,我们介绍了使用Middleware有条件地允许访问路由(<ASP.NET Core使用Middleware有条件地允许访问路由>). 而对于一些试验性的功能,我们并不希 ...

  2. 如何在 ASP.NET Core 中 使用 功能开关

    .NET Core 中的 功能管理 (Feature Management) 包可用于实现 功能开关,什么意思呢?就是可以通过 功能开关 特性动态的改变应用程序的行为而不需要改变任何的业务逻辑代码,听 ...

  3. 【愚公系列】2022年03月 ASP.NET Core中间件-功能开关

    文章目录 前言 1.功能开关的概念 2.功能开关的优点 一.ASP.NET Core中间件实现 1.相关依赖 2.中间件代码 3.在管道中的使用 4.修改配置控制 二.IFeatureFilter过滤 ...

  4. ASP.NET Core使用功能开关控制路由访问(续)

    前言 在前面的文章,我们介绍了使用功能开关控制路由访问. 但其实我们使用了2个条件做的判断: var isDebugEndpoint = context.Request.Path.Value.Cont ...

  5. .NET Core加解密实战系列之——使用BouncyCastle制作p12(.pfx)数字证书

    简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...

  6. .NET Core加解密实战系列之——消息摘要与数字签名算法

    简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...

  7. 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发...

    <ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-tr ...

  8. android 11.0 音量键功能开关(屏蔽音量加减功能)

    1.概述 在11.0 的系统定制化开发中,要求屏蔽掉音量+ 音量-的功能,根据系统属性来判断是否响应音量加减的功能,在系统上层中是由PhoneWindowManage来管理音量键的功能, 所以就要看是 ...

  9. 使用功能开关更好地实现持续部署

    本文转载自InfoQ上文章http://www.infoq.com/cn/articles/function-switch-realize-better-continuous-implementati ...

最新文章

  1. 人工智能值得关注的技术研究方向
  2. MyBatis框架学习 DAY_02:使用XML配置文件/多参数问题 / FOREACH /IF / #{}和${} / 创建SSM框架流程
  3. Codeforces Round #494 (Div. 3)
  4. 光伏产业的发展推动太阳能组件技术进步
  5. OceanBase如何获得TPC-C测试第1名?
  6. pwn环境搭建_pwndbg、pwntools环境搭建(Unix系统)
  7. Mysql常用分组聚合函数(统计行的数量、最大值、最小值、平均值、求和)
  8. Python 编码问题:‘ascii‘ codec can‘t encode characters in position 的解决方案(中文乱码终极解决方案)
  9. Bsie(鄙视IE)
  10. 6-5.添加HLSL顶点着色
  11. Atitit prj tek dfkt 项目常见技术难点目录第一章 开发效率 2第一节 更加简单的语言 2第二节 简单
  12. 华为鸿蒙系统支持什么手机_华为鸿蒙系统支持的手机型号大全,鸿蒙系统2.0支持手机型号汇总[图]...
  13. java基础简答题1
  14. 云计算发展趋势(二)实现云计算的技术以及其他新兴技术介绍
  15. docker制作Nginx镜像
  16. MYSQL数据库版本更新
  17. ISA 95企业和控制系统集成的框架和分层
  18. 公有云平台专题《中移云平台,NB-IoT模组对接中移OneNET平台》
  19. wht can't i allocate a new log
  20. 计算机键盘复制键,键盘按键设置复制粘贴的方法

热门文章

  1. 解决windows系统80端口被占用问题
  2. c/c++ code JSON
  3. Android系统如何实现UI的自适应
  4. 动态更改屏幕方向LANDSCAPE与PORTRAIT 转
  5. 有关技术管理的一些思考
  6. 判断文件是否存在一个API函数
  7. .NET 7 预览版2 的亮点之 NativeAOT 回顾
  8. WPF GridControl控件的用法举例
  9. .net core ——微服务内通信Thrift和Http客户端响应比较
  10. C# 枚举(Enum)