Im ersten Teil wurde ein Überblick über das External Configuration Store Pattern gegeben und den Azure Configuration Service gegeben. In diesem Teil wird eine Implementierung unter Verwendung des Azure Configuration Service gegeben.

Die vollständige Implementierung könnt ihr in meinem GitHub Repository einsehen.

In dem Codebeispiel werden wir die Logging Einstellungen von mehreren Azure Services im Azure Configuration Service abgelegt. Dabei wird gezeigt, wie diese Services bei Änderungen die Einstellungen aktualisieren.

Erstellung des Azure Configuration Service Link to heading

Zuerst erstellen wir den Azure Configuration Service. Hierzu öffnet ihr eine Powershell und wählt die Azure Subscription aus, in der der Config Service angelegt werden soll.

$global:AzResourceGroupName="AppConfigResource-rg"
$global:AzAppConfigName="AppConfigResource-config"

# Create the test resource group
az group create --name $global:AzResourceGroupName --location westeurope
# Create the Azure App Config Store
az appconfig create --location centralus --name $global:AzAppConfigName --resource-group $global:AzResourceGroupName

Write-Host "Created application configuration service " $global:AzAppConfigName

az appconfig kv set --name $global:AzAppConfigName --key Logging:LogLevel:Default --value Information --yes
Write-Host "Added key to " $global:AzAppConfigName

# Get the connection string
az appconfig credential list --name $global:AzAppConfigName

Das oben gezeigte Script erstellt eine Resourcengruppe mit einem Azure Configuration Service. Danach wird die Logging Einstellung als Schlüssel in den Azure Configuration Service erstellt. Am Ende des Scripts wird der Connection String zum Azure Configuration Service angezeigt. Dieser wird später benötigt.

Erstellen einer ASP NET Core API Link to heading

Im nächsten Schritt erstellen wir eine Asp.NET Core WebAPI, die den Azure Configuration Service verwendet. Hierzu erstellen wir das dotnet Projekt und fügen das Nuget Paket für den Azure Configuration Service hinzu.

$serviceName = "myservice"
dotnet new webapi --output $serviceName
cd $serviceName
dotnet add package Microsoft.Azure.AppConfiguration.AspNetCore

Danach öffnen wir das erstellte Projekt mit unseren IDE. Als nächstes sollte dem erstellten dotnet Projekt der ConnectionString bekannt gemacht werden. Öffnet dazu die Datei appsettings.json und fügt die folgenden Zeilen hinzu:

"ConnectionStrings": {
    "AppConfig": "..."
  }

Als Wert für den ConnectionString verwendet Ihr den Connection String aus dem Abschnitt Erstellen der Azure Configuration Service Instanz

Im nächsten Schritt öffnen wird Programm.cs. Dort fügen wir folgenden Startup Code ein:

            ...
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            // Load configuration from Azure App Configuration
            string connectionString = config.GetConnectionString("AppConfig");

            config.AddAzureAppConfiguration(options =>
            {
                options.Connect(connectionString)
                       // Load all keys that start with `Logging:` and have no label
                       .Select($"Logging:{KeyFilter.Any}", LabelFilter.Null)
                       // Configure to reload configuration if the registered sentinel key is modified
                       .ConfigureRefresh(refreshOptions =>
                            refreshOptions.Register("Logging:LogLevel:Default", LabelFilter.Null, refreshAll: true)
                                          .SetCacheExpiration(TimeSpan.FromSeconds(3)));
            });
            services.AddAzureAppConfiguration();

            ...

            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }
            // Add the following line, for getting notified, when the sentinel key has changed
            app.UseAzureAppConfiguration();

            ...

Hier ist eine Beschreibung des Codes:

Zuerst wird die Verbindungszeichenfolge zur Azure App Configuration aus der Anwendungskonfiguration mit dem Namen “AppConfig” abgerufen.

Dann wird die Azure App Configuration über die Methode AddAzureAppConfiguration() konfiguriert. Es werden Optionen festgelegt, um eine Verbindung zur angegebenen Azure App Configuration herzustellen und Konfigurationsdaten zu laden. Außerdem wird definiert, dass alle Schlüssel, die mit “Logging:” beginnen und kein Label haben, geladen werden sollen. Es wird auch konfiguriert, dass die Konfiguration aktualisiert wird, wenn der registrierte Sentinel-Schlüssel (“Logging:LogLevel:Default”) geändert wird. Dies wird mit der Methode ConfigureRefresh() erreicht, die eine Cache-Ablaufzeit von 3 Sekunden für die Konfigurationsdaten festlegt.

Die Azure App Configuration-Dienste werden der Dienstekollektion hinzugefügt, um sie in der Anwendung verfügbar zu machen.

Die Middleware UseAzureAppConfiguration() wird registriert. Diese Middleware sorgt dafür, dass die Anwendung benachrichtigt wird, wenn sich die Konfiguration ändert, insbesondere wenn der Sentinel-Schlüssel geändert wird.

Zusammenfassend verwendet dieser Codeausschnitt Azure App Configuration, um Konfigurationsdaten zu laden und automatisch zu aktualisieren, wenn Änderungen vorgenommen werden. Die Middleware UseAzureAppConfiguration() wird verwendet, um sicherzustellen, dass die Anwendung über Konfigurationsänderungen informiert wird.

Erste Tests Link to heading

Jetzt ist es Zeit zu Testen. Wir können jetzt die Anwendung starten. Die Anwendung sollte fehlerfrei starten. Wenn der Service jetzt getartert wird, dann werden die Konfigurationen zusätzlich aus dem Azure Configuration Service geladen. Der Service sollte jetzt jeden HTTP Request normal im LogLevel Information loggen. Wechselt jetzt in Eure Powershell und führt folgenden Befehl aus:

az appconfig kv set --name $global:AzAppConfigName --key Logging:LogLevel:Default --value Warning --yes

Hiermit habt Ihr das LogLevel Warning gesetzt. Wenn Ihr jetzt weitere Requests gegen Eure API sendet sollten keine LogMeldung geloggt werden.

Weiterführende Gedanken Link to heading

Über das gezeigte Beispiel können wir Konfigurationen von verschiedenen Services zentral verwalten.

Aufbau von Sentinel Keys Link to heading

Ein “Sentinel-Key” ist ein Konzept, das in der Konfigurationsverwaltung verwendet wird, um Änderungen in der Konfiguration zu erkennen und die Aktualisierung der Anwendungskonfiguration auszulösen.

In Bezug auf den obigen Code, wird ein Sentinel-Keys verwendet, um zu überwachen, ob sich die Konfiguration ändert und die Anwendung aktualisiert werden muss. Wenn dieser Schlüssel in der Azure App Configuration geändert wird, löst dies die Aktualisierung der Anwendungskonfiguration aus.

Im Beispielcode wird der Sentinel-Key als “Logging:LogLevel:Default” festgelegt. Wenn sich dieser Schlüssel in der Azure App Configuration ändert, wird die Konfiguration automatisch neu geladen, um die Änderungen zu berücksichtigen.

Für eine verteilte Anwendung sind Überlegungen zum Aubau des Sentinel Keys sinnvoll.

Wahl des Refresh Intervalls Link to heading

Das Refresh-Intervall für die Aktualisierung der Konfiguration hängt von den Anforderungen deiner Anwendung ab. Einige Faktoren, die berücksichtigt werden sollten, sind:

  • Frequenz von Konfigurationsänderungen: Wie oft werden Änderungen an der Konfiguration erwartet? Wenn die Konfiguration relativ stabil ist und selten geändert wird, könnte ein längeres Refresh-Intervall ausreichend sein. Andererseits, wenn die Konfiguration häufig geändert wird, könnte ein kürzeres Intervall erforderlich sein, um sicherzustellen, dass die Anwendung stets die aktuellsten Einstellungen verwendet.

  • Auswirkungen von Konfigurationsänderungen: Wie stark beeinflussen Konfigurationsänderungen die Funktionsweise deiner Anwendung? Wenn Änderungen an der Konfiguration sofortige Auswirkungen haben müssen, ist ein kürzeres Refresh-Intervall erforderlich, um sicherzustellen, dass die Anwendung schnell auf diese Änderungen reagiert.

  • Performance: Ein häufigeres Aktualisieren der Konfiguration kann zu einer höheren Last auf den Konfigurationsservern führen sowie zu einer höheren CPU-Auslastung und Netzwerkbelastung auf Seiten der Anwendung. Daher muss das Refresh-Intervall so gewählt werden, dass es eine angemessene Balance zwischen Aktualität und Performance bietet.

Einige gängige Refresh-Intervalle können im Bereich von Sekunden bis Minuten liegen, je nach den oben genannten Faktoren. Ein Intervall von einigen Sekunden bis zu einigen Minuten ist typisch, aber es ist wichtig, dies basierend auf den spezifischen Anforderungen deiner Anwendung zu entscheiden und möglicherweise durch Tests zu validieren.