.Net Core功能开关实战
為了快速發布開發完成的功能,企業通常會以比較快的迭代周期持續發布。但是由于某些 原因或場景,需要在發布的時候將某些功能隱藏起來或者小規模的開放(例如只有某些特定用戶可以使用、或者特定日期開放),通過使用功能開關(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,代碼如下:
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功能开关实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 持续集成配置之Nuget
- 下一篇: ASP.NET Core应用程序容器化、