前言

我们知道,目前大多数应用程序在正式发布到生产环境之前都会经历多个不同的测试环境,通过让应用程序在多个不同的环境中运行来及时发现并解决问题,避免在线上发生不必要的损失。这是对于整个软件的发布流程来讲。但是如果想让我们的应用程序在线上环境中通过满足一些动态条件(比如电商平台在某一时间段的促销活动)从而能开启一些临时功能的话又该怎么办呢?如果你试图通过重新打包发布的方式来解决这个问题,可能有些过于大动干戈了。本文,笔者将介绍通过 Feature Flag 的方式来解决这个问题。

正文

Feature Flag 中文可译为 功能开关。通过使用这种方式,可以对我们的功能进行条件化配置,当程序在线上环境运行时,如果当前环境符合我们某一特性功能开启/关闭的条件时,应用程序会自动开启/关闭该功能。整个过程不需要人工参与,全部都是由系统本身来完成相应功能的开启和关闭。

那在 .NET Core 中,我们该如何实现该功能呢?

微软为我们很贴心地提供了两个开发包:Microsoft.FeatureManagementMicrosoft.FeatureManagement.AspNetCore,该实现是基于 .NET Core 的配置系统 ,所以任何 .NET Core 程序都可以轻易集成该功能。

目前还处于预览版阶段,需要在 NuGet 上勾选 use prerelease

因此,我们只需将对应包安装到我们的应用程序中即可。

接下来,我们就一起看一下如何在 ASP.NET Core 中集成该功能。

使用入门

创建一个 ASP.NET Core Web Application 后,安装如下包:

Install-Package Microsoft.FeatureManagement.AspNetCore -Version 2.0.0-preview-010610001-1263

接着在 Startup 中的 ConfigureServices 进行相应配置,示例如下:

public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
services.AddControllersWithViews();
}

至此,我们的程序已经支持 Feature Flag 功能了,使用方式就简单了,这里展示一个相对简单的方式。

首先,在 appsettings.json 进行配置,如下所示:

  "FeatureManagement": {
"NewFeatureFlag": true,
}

然后,在 Index.cshtml 通过使用 feature 标签来进行相应配置,示例如下所示:

@using Microsoft.FeatureManagement
@inject IFeatureManager FeatureManager
@addTagHelper *,Microsoft.FeatureManagement.AspNetCore
@{
ViewData["Title"] = "Home Page";
} <div class="text-center">
<h1 class="display-4">Welcome</h1> <feature name="NewFeatureFlag" requirement="All">
<a asp-action="NewFeature">Go to the new feature.</a>
</feature>
</div>

此时,我们运行起程序后就可以看到 feature 标签内的内容就可以渲染出来,如果我们在配置中将 NewFeatureFlag 值设置为 False 后,feature 标签内的内容就会消失,你可以通过查看网页源码的方式来查看具体细节。

接下来笔者介绍一下微软为我们内置的两个功能开关:

PercentageFilter

PercentageFilter 是支持百分比的随机开关,通过使用这种方式,可以让一个功能在每次请求中以一个百分比概率的形式来开启/关闭。

  • 注入功能开关

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement()
.AddFeatureFilter<PercentageFilter>();
services.AddControllersWithViews();
}
  • 配置功能开关

appsettings.json

  "FeatureManagement": {
"RandomFlag": {
"EnabledFor": [
{
"Name": "Percentage",
"Parameters": {
"Value": 50
}
}
]
}
}

这里配置的是在每次请求时以 50% 的概率来开启该功能,其对应的配置类为:PercentageFilterSettings

  • 使用功能开关

Index.cshtml

@using Microsoft.FeatureManagement
@inject IFeatureManager FeatureManager
@addTagHelper *,Microsoft.FeatureManagement.AspNetCore
@{
ViewData["Title"] = "Home Page";
} <div class="text-center">
<h1 class="display-4">Welcome</h1> <feature name="RandomFlag">
<h2>I am a Random Flag!</h2>
</feature> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

这时,当我们运行起程序后就会看到如下图所示的效果:

TimeWindowFilter

TimeWindowFilter 是时间段的随机开关,通过使用这种方式,可以让一个功能在指定的时间段内来开启/关闭。

  • 注入功能开关

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement()
.AddFeatureFilter<TimeWindowFilter>();
services.AddControllersWithViews();
}
  • 配置功能开关

appsettings.json

  "FeatureManagement": {
"RandomFlag": {
"EnabledFor": [
{
"Name": "Percentage",
"Parameters": {
"Start": "2019/12/27 5:04:00 +00:00",
"End": "2019/12/27 5:04:05 +00:00"
}
}
]
}
}

这里需要注意的是,配置里面的 StartEndDateTimeOffset 类型,并且需要配置为 UTC 的时间,所以在实际使用过程中需要考虑时区问题(你可以通过调用 DateTimeOffset.UtcNow 的方式来获取相应时间的格式)。其对应的配置类为:TimeWindowFilterSettings

  • 使用功能开关

Index.cshtml

@using Microsoft.FeatureManagement
@inject IFeatureManager FeatureManager
@addTagHelper *,Microsoft.FeatureManagement.AspNetCore
@{
ViewData["Title"] = "Home Page";
} <div class="text-center">
<h1 class="display-4">Welcome</h1> <feature name="TimedFlag">
<h2>I am a Timed Flag!</h2>
</feature>
<p>@DateTimeOffset.UtcNow.ToString()</p> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

这时,当我们运行起程序后就会看到如下图所示的效果:

自定义功能开关

最后要介绍的是如果创建和使用自定义的功能开关,笔者这里做一个这样的示例,当网站被 Microsoft Edge 浏览器访问时,显示功能,其余浏览器则隐藏功能。

这里,笔者创建一个配置的映射类 BrowserFilterSettings 和执行过滤的操作类 BrowserFeatureFilter,示例代码如下所示:

public class BrowserFilterSettings
{
public string[] AllowedBrowsers { get; set; }
} [FilterAlias("BrowserFilter")]
public class BrowserFeatureFilter : IFeatureFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public BrowserFeatureFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
var userAgent = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
var settings = context.Parameters.Get<BrowserFilterSettings>();
return Task.FromResult(settings.AllowedBrowsers.Any(userAgent.Contains));
}
}

接着,进行功能开关的注入,示例代码如下所示:

public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddFeatureManagement()
.AddFeatureFilter<BrowserFeatureFilter>();
services.AddControllersWithViews();
}

然后,进行功能开关的配置,示例配置如下所示:

  "FeatureManagement": {
"BrowserFlag": {
"EnabledFor": [
{
"Name": "BrowserFilter",
"Parameters": {
"AllowedBrowsers": [
"Edge"
]
}
}
]
}
}

接着,使用方式如下所示:

@using Microsoft.FeatureManagement
@inject IFeatureManager FeatureManager
@addTagHelper *,Microsoft.FeatureManagement.AspNetCore
@{
ViewData["Title"] = "Home Page";
} <div class="text-center">
<h1 class="display-4">Welcome</h1> <feature name="BrowserFlag">
<h2>I am a Browser Flag only on Edge!</h2>
</feature> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

这时,当我们分别用 Microsoft Edge 和 Google Chrome 访问站点时就会看到如下图所示的效果:

总结

借助于 Microsoft.FeatureManagement.AspNetCore 扩展包,我们可以很容易实现 Feature Flag 效果。又由于这种实现是基于 IConfiguration 的,所以很具有通用性。这里列出官方给出的优点:

  • A common convention for feature management
  • Low barrier-to-entry
    • Built on IConfiguration
    • Supports JSON file feature flag setup
  • Feature Flag lifetime management
    • Configuration values can change in real-time, feature flags can be consistent across the entire request
  • Simple to Complex Scenarios Covered
    • Toggle on/off features through declarative configuration file
    • Dynamically evaluate state of feature based on call to server

      API extensions for ASP.NET Core and MVC framework
    • Routing
    • Filters
    • Action Attributes

非常感谢你能阅读这篇文章,希望它能对你有所帮助。

相关参考

给你的 ASP.NET Core 程序插上 Feature Flag 的翅膀的更多相关文章

  1. 如何在ASP.NET Core程序启动时运行异步任务(3)

    原文:Running async tasks on app startup in ASP.NET Core (Part 3) 作者:Andrew Lock 译者:Lamond Lu 之前我写了两篇有关 ...

  2. 如何优雅的利用Windows服务来部署ASP.NET Core程序

    上一篇文章中我给大家讲述了五种部署ASP.NET Core网站的方法,其中有一种方式是通过Windows服务来进行部署,这样既可以做到开启自启动,又不会因为iis的反向代理而损失部分性能.但是美中不足 ...

  3. Asp.Net Core 程序部署到Linux(centos)生产环境(二):docker部署

    运行环境 照例,先亮环境:软件的话我这里假设你已经批准好了.net core 运行环境,未配置可以看我的这篇[linux(centos)搭建.net core 运行环境] 腾讯云 centos:7.2 ...

  4. Asp.Net Core 程序部署到Linux(centos)生产环境(一):普通部署

    运行环境 照例,先亮底 centos:7.2 cpu:1核 2G内存 1M带宽 辅助工具:xshell xftp 搭建.net core运行环境 .net core 的运行环境我单独写了一篇,请看我的 ...

  5. 从头认识一下docker-附带asp.net core程序的docker化部署

    从头认识一下docker-附带asp.net core程序的docker化部署 简介 在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是 ...

  6. .NET CORE学习笔记系列(4)——ASP.NET CORE 程序启用SSL

    一.什么是SSL? 1.概念: SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数 ...

  7. [转帖]以Windows服务方式运行ASP.NET Core程序

    以Windows服务方式运行ASP.NET Core程序 原作者blog: https://www.cnblogs.com/guogangj/p/9198031.htmlaspnet的blog 需要持 ...

  8. ASP.NET Core 程序发布到Linux(Centos7)爬坑实战

    前言 前阶段弄了个Linux系统想倒腾倒腾.NET Core,结果看了下网上的资料,大部分都是过期的,走了不少弯路,不过还好,今下午总算捣鼓出来了.Linux命令太多了,唉.血的教训:安装一定要看官网 ...

  9. ASP.NET Core教程:ASP.NET Core程序部署到Linux

    一.前言 这篇文章我们将讲解如何将ASP.NET Core 程序部署到Linux.这里我们使用的是虚拟机里面安装的Centos7.这里的ASP.NET Core程序,以上篇文章中发布的框架依赖文件为例 ...

随机推荐

  1. AbstractExecutorService的submit方法概要介绍

    1.概述 ExecutorService是JDK提供的框架,它简化了异步模式下的任务执行.一般来说,ExecutorService会自动提供一个线程池和API,用于为其分配任务. 2.实例化Execu ...

  2. java代码简单实现栈

    1. 基于数组简单实现 /** * @author <a herf="mailto:yanwu0527@163.com">XuBaofeng</a> * @ ...

  3. DDoS攻击新趋势:海量移动设备成为新一代肉鸡

    近期,阿里云安全团队观察到数十起大规模的应用层资源耗尽式DDoS攻击(应用层CC攻击).阿里云DDoS高防实现智能防护全程自动化检测并清洗,未对用户侧业务产生任何影响,这类攻击存在一些共同的特征,阿里 ...

  4. Android Http实现文件的上传和下载

    最近做一个项目,其中涉及到文件的上传和下载功能,大家都知道,这个功能实现其实已经烂大街了,遂.直接从网上荡了一堆代码用,结果,发现网上的代码真是良莠不齐,不是写的不全面,就是有问题,于是自己重新整理了 ...

  5. 学习C#泛型

    C#泛型详解 C#菜鸟教程 C#中泛型的使用

  6. day5_python之hashlib模块

    用来校验文本内容hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法三个特点:1.内容相同则h ...

  7. iptables 累计(Accounting)

    对於每一条规则,核心各自设置两个专属的计数器,用于累计符合该条件的封包数,以及这些封包的总位元组数.这两项资讯可用於统计网路用量. 举例来說,假设有一台Internet闸道器路,eth0接内部网络,e ...

  8. uni-app中使用Echarts绘画图表

    enmnm...一般会使用npm下载echarts这个包,但是不知道是我自己的配置问题还是别的原因,一直出不来图线, 于是,把Hello uni-app模板里的那个组件抱过来,然后,成了! 首先, 1 ...

  9. jqLite

    一.关于DOM导航的jqLite方法 children() 返回一组子元素.这个方法的jqLite实现不支持jQuery所提供的选择器特性 eq(index) 从一个元素集合中返回指定索引下的元素 f ...

  10. 2018百度之星初赛B - A,D,F

    总结:这一次的百度之星之行到这里也就结束了,充分的认识到了自己的不足啊...果然还是做的题太少,,见识的题型也还太少,对于STL的掌握还是不够到位啊!!(STL大法是真的好,建议大家认认真真的好好学学 ...