Phần 3 - Tạo cờ tính năng động với bộ lọc tính năng

Đây là bài thứ 3 trong loạt bài: Thêm cờ tính năng vào ứng dụng ASP.NET Core.

Trong bài đầu tiên của loạt bài này, tôi đã giới thiệu thư viện Microsoft.FeatureManagement và hướng dẫn cách sử dụng nó để thêm các cờ tính năng vào ứng dụng ASP.NET Core.

Trong bài viết thứ 2, tôi giới thiệu thư viện bổ sung là Microsoft.FeatureManagement.AspNetCore. Thư viện này bổ sung các tính năng dành riêng cho ASP.NET Core để làm việc với cờ tính năng, chẳng hạn như Tag Helper và Action Filter.

Trong bài viết này, tôi giới thiệu các bộ lọc tính năng (feature filter), đây là một cách hoạt động mạnh mẽ hơn nhiều với cờ tính năng. Điều này cho phép bạn kích hoạt một tính năng dựa trên dữ liệu tùy ý.

Ví dụ: bạn có thể bật một tính năng dựa trên tiêu đề trong một yêu cầu đến, dựa trên thời gian hiện tại hoặc dựa trên yêu cầu của người dùng hiện tại.

Trong bài viết này, tôi sẽ hướng dẫn cách sử dụng hai bộ lọc tính năng có trong thư viện Microsoft.FeatureManagement là PercentageFilterTimeWindowFilter.

Mở rộng cờ tính năng ngoài kiểu Boolean đơn giản

Cho đến nay trong loạt bài này, tôi đã trình bày bằng cách sử dụng cờ tính năng được "cố định" trong cấu hình:

{
  "FeatureManagement": {
    "Beta": false
  }
}

Với cấu hình này, cờ tính năng Beta luôn false dành cho tất cả người dùng (cho đến khi cấu hình thay đổi). Mặc dù điều này sẽ hữu ích trong một số trường hợp, nhưng bạn thường có thể chỉ muốn bật các tính năng cho một số người dùng của mình hoặc chỉ một số thời điểm.

Ví dụ: có thể bạn đang làm việc trên một tính năng mới và bạn chỉ muốn một vài người dùng của mình có thể nhìn thấy nó, trong trường hợp có bất kỳ vấn đề nào với nó. Ngoài ra, có thể bạn đang chạy chương trình khuyến mại trên một cửa hàng và bạn chỉ muốn bật biểu ngữ trong một khoảng thời gian cụ thể. Cả hai tùy chọn này đều không khả thi với các cờ đơn giản mà chúng ta đã thấy cho đến nay.

Microsoft.FeatureManagement giới thiệu interface IFeatureFilter có thể được sử dụng để quyết định xem một tính năng có được bật hay không dựa trên bất kỳ logic nào bạn yêu cầu. Hai cách triển khai đơn giản là TimeWindowFilterPercentageFilter tôi sẽ giới thiệu bên dưới.

Bật tính năng dựa trên thời gian hiện tại với TimeWindowFilter

TimeWindowFilter đúng như tên gọi của nó - nó cho phép một tính năng trong một khoảng thời gian nhất định. Bạn cung cấp phần bắt đầu và phần kết thúc DateTime và mọi cuộc gọi tới phương thức IFeatureManager.IsEnabled() sẽ trả về true trong khoảng thời gian đó.

Ví dụ dưới đây tiếp tục từ các bài viết trước, vì vậy nó giả sử bạn đã cài đặt gói NuGet. TimeWindowFilterPercentageFilter có sẵn trong thư viện .NET Standard Microsoft.FeatureManagement, vì vậy bạn có thể sử dụng nó trong bất kỳ ứng dụng .NET Standard nào. Tôi sẽ giả sử đó là một ứng dụng ASP.NET Core cho bài viết này.

Thêm các dịch vụ quản lý tính năng vào Startup.ConfigureServices, bằng cách gọi phương thức AddFeatureManagement(), nó trả về một IFeatureManagementBuilder. Bạn có thể bật bộ lọc TimeWindowFilter bằng cách gọi AddFeatureFilter<>():

using Microsoft.FeatureManagement;
using Microsoft.FeatureManagement.FeatureFilters;

public class Startup 
{
    public void ConfigureServices(IServiceCollection services)
    {
        //...
        services.AddFeatureManagement()
            .AddFeatureFilter<TimeWindowFilter>();
    }
}

Điều này thêm IFeatureFilter vào ứng dụng của bạn, nhưng bạn cần phải cấu hình nó bằng cách sử dụng hệ thống cấu hình. Mỗi IFeatureFilter có thể có một đối tượng "cài đặt" được liên kết, tùy thuộc vào việc triển khai. Đối với TimeWindowFilter, điều này trông giống như:

internal class TimeWindowSettings
{
    public DateTimeOffset? Start { get; set; }
    public DateTimeOffset? End { get; set; }
}

Vì vậy, hãy xem xét một tình huống: Tôi muốn bật banner Giáng sinh tùy chỉnh phát trực tiếp vào ngày 26/12 lúc 2 giờ sáng UTC và kết thúc ba ngày sau đó lúc 1 giờ sáng UTC.

Chúng ta sẽ bắt đầu bằng cách tạo cờ tính năng cho nó trong mã có tên ChristmasBanner

public static class FeatureFlags
{
    public const string ChristmasBanner = "ChristmasBanner";
}

Bây giờ chúng ta sẽ thêm cấu hình. Như trước đây, chúng ta đưa cấu hình trong khóa FeatureManagement và cung cấp tên của đối tượng feature. Tuy nhiên, thay vì sử dụng Boolean cho đối tượng feature, chúng ta sử dụng EnabledFor và chỉ định một loạt các bộ lọc đối tượng feature.

{
  "FeatureManagement": 
  {
    "ChristmasBanner": 
    {
      "EnabledFor": 
      [
        {
          "Name": "Microsoft.TimeWindow",
          "Parameters": 
          {
            "Start": "26 Dec 2019 02:00:00 +00:00",
            "End": "29 Dec 2019 01:00:00 +00:00"
          }
        }
      ]
    }
  }

Điều quan trọng là bạn có được cấu hình chính xác ở đây. Mẫu chung giống hệt nhau cho tất cả các bộ lọc tính năng:

  • Tên đối tượng ("ChristmasBanner") phải là khóa của một đối tượng.
  • Đối tượng này phải chứa một thuộc tính duy nhất, EnabledFor là một mảng các đối tượng.
  • Mỗi đối tượng trong mảng đại diện cho một IFeatureFilter. Đối với mỗi bộ lọc. Cung cấp Name của bộ lọc ("Microsoft.TimeWindow") cho TimeWindowFilter. Tùy chọn cung cấp một đối tượng Parameters, được liên kết với đối tượng cài đặt của bộ lọc tính năng (TimeWindowSettings trong trường hợp này).
  • Nếu bất kỳ bộ lọc tính năng nào trong mảng đáp ứng cho một yêu cầu nhất định, tính năng được bật. Nó chỉ bị vô hiệu hóa nếu tất cả các IFeatureFilter chỉ ra rằng nó nên được vô hiệu hóa.

Với cấu hình này, cờ tính năng ChristmasBanner sẽ trả về false cho đến khi DateTime.UtcNow rơi vào giữa các ngày đã cho:

using Microsoft.FeatureManagement;

public class IndexModel : PageModel
{
    private readonly IFeatureManager _featureManager;
    public IndexModel(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
        // only returns true during provided time window
        var showBanner = _featureManager.IsEnabled(FeatureFlags.ChristmasBanner);
    }
    // ...
}

Lợi ích thực sự của việc sử dụng IFeatureFilter là bạn có được hành vi động, nhưng bạn vẫn có thể kiểm soát nó từ cấu hình.

Lưu ý rằng TimeWindowSettings có giá trị nullable cho Start End, để cung cấp cho bạn cửa sổ thời gian kết thúc mở, ví dụ: luôn bật cho đến một ngày nhất định hoặc chỉ bật từ một ngày nhất định.

Bật tính năng dựa trên phần trăm yêu cầu với PercentageFilter

Bộ lọc PercentageFilter cũng hoạt động như bạn có thể mong đợi - nó chỉ bật một tính năng cho x phần trăm yêu cầu, với x được kiểm soát thông qua cài đặt. Kích hoạt bộ lọc PercentageFilter theo cùng một quy trình như đối với TimeWindowFilter.

Thêm PercentageFilter vào ConfigureServices() như sau:

using Microsoft.FeatureManagement;
using Microsoft.FeatureManagement.FeatureFilters;

public class Startup 
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddFeatureManagement()
            .AddFeatureFilter<PercentageFilter>();
    }
}

Tạo cờ tính năng:

public static class FeatureFlags
{
    public const string FancyFonts = "FancyFonts";
}

Cấu hình tính năng trong cấu hình:

{
  "FeatureManagement": 
  {
    "FancyFonts": 
    {
      "EnabledFor": 
      [
        {
          "Name": "Microsoft.Percentage",
          "Parameters": 
          {
            "Value": 10
          }
        }
      ]
    }
  }
}

Đối tượng PercentageSettings bao gồm một đối tượng kiểu int, là phần trăm thời gian cờ nên được bật. Trong ví dụ trên, cờ sẽ được bật cho 10% cuộc gọi đến IFeatureManager.IsEnabled(FeatureFlags.FancyFonts).

Câu cuối cùng đó có thể hơi khó hiểu đối với bạn. Điều đó có nghĩa là nếu bạn gọi IsEnabled() hai lần trong cùng một yêu cầu, thì PercentageFilter có thể đưa ra các câu trả lời khác nhau? Vâng!

Trên hết, các yêu cầu tiếp theo sẽ có cùng tiềm năng lật qua lại, vì vậy người dùng có thể thấy các tính năng xuất hiện khi họ duyệt qua trang web của bạn.

May mắn thay, có những giải pháp cho cả hai vấn đề này được tích hợp trong thư viện, nhưng tôi sẽ để lại chúng cho một bài viết sau.

Hai bộ lọc hiển thị ở đây được tích hợp sẵn trong Microsoft.FeatureManagement, nhưng bạn có thể tự triển khai bộ lọc của riêng mình. Trong bài viết tiếp theo, tôi sẽ hướng dẫn cách tạo một IFeatureFilter tùy chỉnh cho phép các tính năng dựa trên người dùng hiện đang đăng nhập.

Tóm lược

Microsoft.FeatureManagement cho phép bạn bật cờ tính năng dựa trên các giá trị trong cấu hình. Bằng cách sử dụng IFeatureFilter, bạn có thể nhận được hành vi động, mặc dù cấu hình của bạn có thể là tĩnh.

Bộ lọc TimeWindowFilterPercentageFilter được bao gồm trong thư viện và cung cấp các cờ tính năng động cơ bản. Để thêm chúng vào ứng dụng của bạn, bạn phải kích hoạt chúng bằng cách gọi phương thức AddFeatureFilter<>() trong Startup.ConfigureServices() và thêm cấu hình thích hợp.

Series: Thêm cờ tính năng vào ứng dụng ASP.NET Core
Trong loạt bài này, tôi sẽ trình bày cách tạo các cờ tính năng vào ứng dụng ASP.NET Core sử dụng thư viện Microsoft.FeatureManagement.
ASP.NET Core.NET CoreASP.NET Core MVCLập Trình C#
Bài Viết Liên Quan:
Phần 6 - Các lựa chọn thay thế cho Microsoft.FeatureManagement
Trung Nguyen 13/03/2022
Phần 6 - Các lựa chọn thay thế cho Microsoft.FeatureManagement

Trong bài viết này, tôi giới thiệu sơ lược về một số lựa chọn thay thế cho thư viện Microsoft.FeatureManagement và mô tả sự khác biệt của chúng

Phần 5 - Đảm bảo cờ tính năng nhất quán trên các yêu cầu
Trung Nguyen 13/03/2022
Phần 5 - Đảm bảo cờ tính năng nhất quán trên các yêu cầu

Trong bài viết này, tôi giới thiệu hai cách để cải thiện tính nhất quán của cờ tính năng cho mọi yêu cầu đối với người dùng trong ứng dụng ASP.NET Core.

Phần 4 - Tạo bộ lọc tính năng tùy chỉnh
Trung Nguyen 13/03/2022
Phần 4 - Tạo bộ lọc tính năng tùy chỉnh

Trong bài viết này, tôi sẽ chỉ cho bạn cách tạo bộ lọc tính năng tùy chỉnh của riêng mình bằng cách sử dụng IFeatureFilter trong ASP.NET Core.

Phần 2 - Lọc các action method với cờ tính năng
Trung Nguyen 12/03/2022
Phần 2 - Lọc các action method với cờ tính năng

Trong bài này, tôi giới thiệu thư viện Microsoft.FeatureManagement.AspNetCore bổ sung các tính năng dành riêng cho ASP.NET Core để làm việc với cờ tính năng