Jak zarządzać feature flags w aplikacjach ASP.NET Core przy użyciu Azure?

geek.justjoin.it 1 rok temu

Niezależnie od tego czy aplikacja jest prosta, czy bardziej złożona, wybór adekwatnego dostawcy konfiguracji na samym początku ułatwi późniejsze zarządzanie feature flags i dodawanie odpowiednich filtrów.

W moich artykułach dostępnych na blogu Predica Group opisałem, czym są feature flags i jak je implementować w aplikacjach .NET. jeżeli potrzebujesz ogólnego przeglądu, zalecam rozpoczęcie od tych dwóch wpisów.

Gdy zarządzanie feature flags zostanie skonfigurowane, trzeba zdecydować, gdzie je przechowywać. jeżeli chcesz się dowiedzieć, jakie narzędzie jest przeze mnie preferowane i dlaczego, przeczytaj poniższy artykuł.

Gdzie najlepiej przechowywać konfigurację feature flags?

W artykule wprowadzającym opisałem bibliotekę Microsoft.FeatureManagement jako pomocne narzędzie w implementacji feature flags. Co więcej, jest ono użyteczne również w przypadku przechowywania feature flags.

Biblioteka Microsoft.FeatureManagement działa na standardowej konfiguracji ASP.NET Core, dzięki czemu można wybrać dowolnego dostawcę konfiguracji.

Przykładem mogą być zmienne środowiskowe lub pliki appsettings.json:

„FeatureManagement”: { "UseExtremeScaling": false, "UsePromotionCoupons": { "EnabledFor": [ { "Name": "Microsoft.Targeting", "Parameters": { "DefaultRolloutPercentage": 1 }, }, ], }, },

Wybór najlepszego dostawcy konfiguracji dla zarządzania funkcjami zależy głównie od stopnia złożoności aplikacji.

W przypadku bardzo prostych aplikacji, pliki JSON i zmienne środowiskowe będą prawdopodobnie wystarczające.

Jednak gdy w projekcie zaimplementowano wiele różnych feature flags i chcesz mieć przyjazny dla użytkownika portal do przeglądania i edycji konfiguracji przełączników funkcji, warto skorzystać z Azure App Configuration.

Czym jest Azure App Configuration?

Jest to usługa przechowywania konfiguracji w chmurze Azure, która umożliwia zespołom deweloperskim zarządzanie parametrami aplikacji w czasie rzeczywistym, bez konieczności wdrażania kodu. Rozwiązanie to jest szybkie, skalowalne i bezpieczne.

Z perspektywy przełączników funkcji, kluczową możliwością jest wbudowane wsparcie dla zarządzania funkcjami.

Ponadto panel administracyjny dla feature flags jest funkcjonalny i atrakcyjny wizualnie:

W panelu możesz włączać/wyłączać proste feature flags, a także korzystać z wbudowanego edytora konfiguracji dla filtrów, takich jak:

  • Okno czasowe
  • Docelowość
  • Niestandardowe (własne filtry)

Jeśli nie jesteś zaznajomiony z filtrami funkcji, gorąco zachęcam do zapoznania się z moim artykułem, w którym bardziej szczegółowo je opisuję.

Inną wielką korzyścią jest scentralizowane przechowywanie konfiguracji zarządzania funkcjami. Na pewno się to przyda, jeżeli masz do czynienia z wieloma (mikro)usługami, które korzystają z tych samych feature flags.

Na koniec, integracja z Microsoft.FeatureManagement to prawdziwa bułka z masłem.

Azure App Configuration to po prostu kolejny dostawca konfiguracji .NET, więc po podłączeniu aplikacji do niego, feature flags są automatycznie skonfigurowane.

Jak utworzyć nowe repozytorium Azure App Configuration?

Najłatwiejszym sposobem na uruchomienie Azure App Configuration jest użycie Azure Portal.

Oto co musisz zrobić:

1. Najpierw otwórz Azure Portal i kliknij przycisk „Create a resource”:

2. Następnie wybierz „App Configuration” z paska wyszukiwania:

3. Następnie kliknij przycisk „Create”:

4. Teraz musimy podać wszystkie niezbędne szczegóły, takie jak resource group, lokalizacja, nazwa zasobu, opcje odzyskiwania i poziom cenowy.

Jeśli nie jesteś pewien, co wybrać, sprawdź poziomy cenowe w dokumentacji Azure, aby wybrać plan odpowiadający Twoim potrzebom.

5. Następnie możesz dodać tagi i skonfigurować sieć dla Azure App Configuration (np. aby umożliwić dostęp tylko dla określonej sieci wirtualnej Azure).

Dla zwięzłości pomińmy ten krok i kliknij “Review + Create”.

Po zakończeniu poprawnej walidacji możemy utworzyć Azure App Configuration, korzystając z przycisku “Create”:

6. Po kilku minutach powinno zostać utworzone gotowe do użycia Azure App Configuration.

7. Na koniec możemy przejść do strony zasobu, aby zobaczyć podsumowanie naszego Azure App Configuration:

Przydatne podstrony, z którymi warto się zapoznać to:

  • Access Keys – gdzie możesz uzyskać klucz dostępu potrzebny do połączenia aplikacji z zasobem
  • Feature Manager – ekran zarządzania feature flags, który pokazałem na początku tego artykułu

Na chwilę teraz opuśćmy Azure Portal i przejdźmy do kodu źródłowego aplikacji, gdzie połączymy ją z Azure App Configuration.

Jak dodać Azure App Configuration do projektu?

W tym momencie przypuszczam, iż już dodał*ś bibliotekę Microsoft.FeatureManagement do swojej aplikacji.

Jeśli nie jesteś pewien/na, jak to zrobić, możesz znaleźć więcej instrukcji i postępować zgodnie z krokami opisanymi w moim poprzednim artykule.

Jak zwykle, zaczniemy od zainstalowania pakietu NuGet:

dotnet add package Microsoft.Azure.AppConfiguration.AspNetCore

Następnie możemy zarejestrować Azure App Configuration jako dostawcę konfiguracji dzięki poniższego kodu:

// Program.cs Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => webBuilder.ConfigureAppConfiguration(config => { var settings = config.Build(); config.AddAzureAppConfiguration(appConfig => appConfig.Connect(settings["AppConfig:ConnectionString"].UseFeatureFlags()) }).UseStartup<Startup>());

Polega to na pobraniu connection string Azure App Configuration z bieżącej konfiguracji, a następnie zarejestrowaniu Azure App Configuration jako nowego dostawcy konfiguracji.

Metoda UseFeatureFlags umożliwia przechowywanie feature flags Azure App Configuration w sekcji konfiguracji FeatureManagement, co jest potrzebne dla Microsoft.FeatureManagement.

To zachowanie można skonfigurować, i niedługo powrócimy do tego fragmentu kodu.

Kolejnym krokiem jest zarejestrowanie Azure App Configuration w kontenerze DI (Dependency Injection) i dodanie odpowiednich middleware request pipeline.

using Microsoft.Extensions.Configuration; public class Startup { public void ConfigureServices(IServiceCollection services) { // ... services.AddAzureAppConfiguration(); // <- Add this line // ... } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAzureAppConfiguration(); // <- Add this line app.UseHttpsRedirection(); app.UseRouting(); // ... } }

Przed uruchomieniem aplikacji musimy podać ciąg połączenia Azure App Configuration. Możemy go znaleźć w Azure Portal na podstronie klucze dostępu (Access Keys).

Możliwe jest również skonfigurowanie połączenia bez użycia kluczy dostępu, ale z użyciem tożsamości zarządzanych przez Azure Active Directory do uwierzytelnienia.

Do użytku produkcyjnego polecam sprawdzenie tej strony, aby dowiedzieć się więcej.

Skopiujmy ciąg połączenia do użycia w aplikacji.

Podczas inicjalizacji aplikacji otrzymujemy wartość dla klucza AppConfig:ConnectionString.W pliku appsettings.json wyglądałoby to tak:

{ "AppConfig" : { "ConnectionString" : "SECRET", } }

Umieszczenie ciągu połączenia w pliku appsettings.json jest kuszące, ale jeżeli chodzi o bezpieczeństwo, stworzyłoby to potencjalne ryzyko. Co jak co ale są to wrażliwe dane, dlatego należy je przechowywać ostrożnie.

Lokalnie możesz skorzystać z ASP.NET. Core user secrets oraz App Service Configuration w portalu Azure na produkcji lub, co lepsze, Azure Key Vault.

I to wszystko. Aplikacja może teraz korzystać z Azure App Configuration jako magazynu feature flags, a Ty możesz zmieniać konfigurację w czasie rzeczywistym.

Dodajmy więc pierwszą feature flag do Azure App Configuration.

Jak zarządzać feature flags w Azure App Configuration?

Najpierw dodamy feature flag UsePromotionCoupons do App Configuration.

W artykule zaznamiającym z feature flags wyjaśniałem, jak ją dodać do aplikacji, więc jeżeli jest Ci to obce, przejdź najpierw tam.

Zaczniemy od przejścia do podstrony menedżera funkcji w portalu Azure. Następnie kliknij przycisk “Create”, aby dodać nową feature flag i nadaj jej nazwę.

Klucz zostanie automatycznie uzupełniony na podstawie nazwy, ale wrócimy do tego później.

Możemy również dodać etykietę oraz opis, włączyć feature flag i skonfigurować filtry funkcji.

Na koniec klikamy przycisk “Apply”. Feature flag zostanie utworzona i będzie widoczna na podstronie menedżera funkcji.

Kiedy teraz uruchomisz aplikację, powinna ona odczytać wartość feature flag z Azure App Configuration, a wartość można zmieniać z podstrony menedżera funkcji. Nie jest wymagane ponowne uruchomienie!

Jednak pamiętaj, iż wartości Azure App Configuration są buforowane w aplikacji.

Domyślnie fature flags są buforowane przez 30 sekund. W dalszej części artykułu pokażę Ci, jak to zmienić.

Jak skonfigurować filtry funkcji?

Już wiesz, jak włączać/wyłączać flagi funkcji w Azure App Configuration.

Jednak jeżeli czytałeś mój artykuł wprowadzający, prawdopodobnie pamiętasz, iż możemy również używać filtrów funkcji, aby włączać feature flag, gdy spełniony jest określony warunek.

Biblioteka Microsoft.FeatureManagement ma dwa wbudowane filtry:

  • Targeting – umożliwia włączanie funkcji dla określonej grupy lub udziału wszystkich użytkowników aplikacji (np. tylko 1% wszystkich użytkowników będzie miało dostęp do funkcji)
  • Time window – umożliwia włączanie feature flags dla wszystkich użytkowników w określonym czasie (np. tylko w ten weekend)

Oba z nich są obsługiwane przez Azure App Configuration i można je skonfigurować na podstronie menedżera funkcji.

Oto przegląd filtra funkcji Targeting:

Poniżej widać jak skonfigurować drugi rodzaj filtru, czyli Time window:

Po zapisaniu zmian filtr zostanie zsynchronizowany z aplikacją. jeżeli jest poprawnie zarejestrowany, powinien działać bez konieczności restartowania aplikacji (ale zwróć uwagę na pamięć podręczną!).

Jeśli z jakiegoś powodu wbudowane filtry nie spełniają Twoich oczekiwań, istnieje jeszcze jedna opcja: dodanie niestandardowych filtrów cech.

W artykule wprowadzającym z tej serii pokazałem Ci, jak zbudować ClaimsCheckFeatureFilter, i będziemy postępować tak samo i tutaj:

using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.FeatureManagement; namespace Predica.FeatureFlagsExample; [FilterAlias("ClaimsCheck")] public class ClaimsCheckFeatureFilter : IFeatureFilter { private readonly IHttpContextAccessor _httpContextAccessor; public ClaimsCheckFeatureFilter(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context) { var settings = context.Parameters.Get<ClaimsCheckFeatureFilterSettings>() ?? new ClaimsCheckFeatureFilterSettings(); var strValue = _httpContextAccessor.HttpContext?.User.FindFirstValue( settings.ClaimType); var parsed = bool.TryParse(strValue, out var claimValue); var isFeatureOn = parsed && claimValue; return Task.FromResult(isFeatureOn); } }

Tutaj będzie trzeba dostosować ustawienia dla ClaimType.

namespace Predica.FeatureFlagsExample; public class ClaimsCheckFeatureFilterSettings { public string ClaimType { get; set; } }

Możesz przechowywać go w konfiguracji Azure App Configuration.

Podczas edycji strony, wybierz „Custom” i nadaj mu nazwę. Pamiętaj, aby dopasować go do typu lub aliasu:

Następnie, dodaj parametr dla filtru, wybierając „edit filter parameters” z menu rozwijanego:

Na koniec, podaj nazwę parametru i jego wartość:

I to wszystko! Pomyślnie skonfigurowałeś niestandardowy filtr.

Podobnie jak w przypadku innych wbudowanych filtrów, nie musisz restartować aplikacji, jeżeli filtr jest w niej zarejestrowany.

Jak buforować feature flags przechowywane w Azure App Configuration?

Jak wspomniałem wcześniej, feature flags są ukryte przez Azure App Configuration, aby uniknąć niepotrzebnego zużycia zasobów, takich jak CPU czy przepustowość sieciowa.

Domyślnie feature flags są buforowane przez 30 sekund, ale łatwo możemy to zmienić podczas inicjalizacji aplikacji:

// Program.cs Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => webBuilder .ConfigureAppConfiguration(config => { var settings = config.Build(); config.AddAzureAppConfiguration(appConfig => appConfig.Connect(settings["AppConfig:ConnectionString"]) .UseFeatureFlags(featureFlagsConfig => { // Add this config featureFlagsConfig.CacheExpirationInterval = TimeSpan.FromSeconds(5); })); }) .UseStartup<Startup>());

Właściwość CacheExpirationInterval kontroluje czas, jaki musi upłynąć przed aktualizacją feature flags z App Configuration. Nie może być mniejsza niż jedna sekunda, ale nie ma maksymalnej wartości wygaśnięcia zmian.

Zgodnie z powyższym przykładem kodu, aplikacja jest skonfigurowana tak, aby odświeżać bufor co pięć sekund.

Jak filtrować feature flags?

Jeśli mamy aplikację z kilkoma feature flags i tylko jednym środowiskiem, zarządzanie feature flags jest dość proste.

Ale co w przypadku bardziej złożonych scenariuszy? Załóżmy, iż aplikacja ma dwa środowiska:

  • środowisko deweloperskie – używane tylko do celów deweloperskich
  • środowisko produkcyjne – działająca aplikacja obsługująca rzeczywiste obciążenie

Wyobraźmy sobie, iż chcemy ustawić feature flags z różnymi wartościami dla wszystkich środowiska. Na przykład, włączamy funkcję w środowisku deweloperskim, ale wyłączamy ją w drugim.

Oczywiście, możemy mieć dedykowany App Configuration dla wszystkich środowiska. Jednak byłoby to dość kosztowne, więc aby zmniejszyć rachunek za usługi chmurowe, mamy tylko jedną instancję obejmującą oba środowiska aplikacji.

Na szczęście Azure App Configuration oferuje przydatną opcję o nazwie etykiety (labels), która idealnie pasuje do tego scenariusza.

W skrócie możemy mieć wiele feature flags o tej samej nazwie, ale różnych etykietach, dzięki czemu nasza aplikacja będzie pobierać tylko feature flags z predefiniowanymi etykietami.

Oto jak można je utworzyć:

Następnie można je włączyć dla określonego środowiska:

Aby włączyć tę opcję, musimy jednak zmienić inicjalizację aplikacji, aby mogła pobierać flagi ze zdefiniowanymi etykietami:

// Program.cs Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => webBuilder .ConfigureAppConfiguration(config => { var settings = config.Build(); config.AddAzureAppConfiguration(appConfig => appConfig.Connect(settings["AppConfig:ConnectionString"]) .UseFeatureFlags(featureFlagsConfig => { featureFlagsConfig.CacheExpirationInterval = TimeSpan.FromSeconds(5); // Add this line featureFlagsConfig.Label = settings["AppConfig:Label"]; })); }) .UseStartup<Startup>());

Kod powyżej filtruje feature flags o tych samych etykietach, które są podane w ustawieniach aplikacji w sekcji AppConfig, we adekwatności Label.

Możesz przechowywać je u dowolnego dostawcy konfiguracji obsługiwanego przez Twoją aplikację, na przykład w pliku appsettings.json lub zmiennych środowiskowych.

Jeśli ustawisz etykietę na „dev” dla środowiska developerskiego i „prod” dla środowiska produkcyjnego, Twoja aplikacja będzie wybierać tylko odpowiednie feature flags.

Podsumowanie

Mam nadzieję, iż przedstawiłem wystarczająco dużo dowodów na to, iż App Configuration to dobre rozwiązanie do przechowywania feature flags. Może okazać się to bardzo pomocne, gdy będziesz mieć wiele aplikacji (może mikroserwisów), które korzystają z tych samych feature flags.

Ponadto posiada wygodny interfejs użytkownika do zarządzania funkcjami, który pomaga w przeglądzie wszystkich przełączników funkcji w Twoim systemie.

I na koniec, łatwo integruje się z potężną biblioteką Microsoft.FeatureManagement.Jeśli chcesz wdrażać podobne rozwiązania dla naszych klientów, zajrzyj na stronę Join us i zostań Predicanem.

Nauka programowania, work-life balance, a może zarobki w IT?

Powiedz nam, o czym najchętniej czytasz. Chcemy poznać Cię lepiej – po to, by dobierać jeszcze bardziej interesujące treści!

Zdjęcie główne pochodzi z Unsplash.com.

Idź do oryginalnego materiału