ASP.NET Core

Wissen Sie, ob bei Ihrer API alles OK ist?

Moderne APIs basieren auf einer Vielzahl von Komponenten, die alle funktionieren müssen, um zu einem stimmigen Gesamtergebnis zu kommen. Um Probleme proaktiv zu entdecken, gibt es eine Vielzahl von Überwachungstools, die die Funktionsfähigkeit einer Anwendung regelmäßig prüfen. Hierbei kommen für APIs sogenannte Health Checks zum Einsatz. Das sind spezielle Requests, deren Ergebnis über den Systemzustand Aufschluss gibt. Idealerweise frägt man hierbei nicht einfach irgendeinen Endpunkt der Anwendung ab, sondern stellt einen dedizierten Endpunkt zur Verfügung, so dass die normale Systemaktivität nicht beeinflusst wird.

Das Registrieren eines solchen Endpunkts ist sehr einfach:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddHealthChecks();
    // ...
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, TimeTrackingContext ctx)
{
    // ...
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapHealthChecks("/health");
    });
    // ...
}

Obenstehender Code erstellt einen Endpunkt für die Health Checks, der unter der Route “health” erreicht werden kann. Somit kann die grundlegende Funktion der API schon geprüft werden.

Absichern des Endpunkts

Mit der obigen Einstellung ist der Endpunkt ohne Authentifzierung und Autorisierung erreichbar. Insbesondere bei öffentlich gehosteten APIs sollte man jedoch sicherstellen, dass Informationen über den Systemzustand nur für autorisierte Personen bzw. Dienste zur Verfügung stehen. Über das Hinzufügen von `RequireAuthorization” beim Mappen des Health Check-Endpunkts kann man sicherstellen, dass eine Autorisierung notwendig ist:

endpoints.MapHealthChecks("/health").RequireAuthorization();

Damit wird die Autorisierung mit dem allgemein für die Anwendung verwendeten Schema vorgenommen. Häufig ist es jedoch so, dass die Überwachungsinfrastruktur nur bestimmte Authentifizierungsmöglichkeiten anbietet, so dass ein gesondertes Authentification Scheme erforderlich wird. Ein gängiges Beispiel ist, dass die API über JWT Bearer Tokens abgesichert wird, der Health Check jedoch über Basic Auth erreichbar ist. Einen Überblick über die Authentifizierung in ASP.NET Core und über Authentification Schemes bietet folgende Dokumentation. Um für den Health Check eine eigene Autorisierungsrichtlinie (Authorisation Policy) zu verwenden, kann man den Namen dieser als Parameter bei RequireAuthorization angeben:

endpoints.MapHealthChecks("/health").RequireAuthorization("HealthCheckAuthorizationPolicy");

Prüfung von Teilkomponenten

Sicherzustellen, dass die API erreichbar ist, ist ein Anfang. Normalerweise setzen APIs auf weiteren Komponenten auf, die zur Funktionsfähigkeit erforderlich sind, beispielsweise einer Datenbank. Die Health Checks in ASP.NET Core sind erweiterbar gestaltet, so dass man eigene Health Checks einfach implementieren kann. Eine Anleitung ist hier zu finden.

Glücklicherweise stellt das Community-Projekt AspNetCore.Diagnostics.HealthChecks eine Vielzahl an Health Checks für gängige Komponenten zur Verfügung (Liste der Komponenten). Als Beispiel zeigen wir hier den Health Check für die Verbindung zu einem SQL Server. Hierzu installiert man das Nuget-Paket AspNetCore.HealthChecks.SqlServer im Projekt und registriert den Health Check:

services.AddHealthChecks()
    .AddSqlServer(connectionString);

Dieser Health Check verifiziert mit einem einfachen Statement die Verbindung zum angegebenen Server, so dass eine Downtime des SQL Servers entdeckt werden kann.

Ausgabe von detaillierten Informationen

In der Standardvariante gibt der Endpunkt neben dem Status Code nur den allgemeinen Status des Health Checks in Textform zurück, also beispielsweise Healthy oder Unhealthy. Um die Behebung des Problems im Fehlerfall zielgerichtet angehen zu können, ist es natürlich hilfreich, wenn genauere Informationen ausgegeben werden. Dazu kann man die Ausgabe des Endpunkts anpassen, indem man eine eigene Funktion schreibt:

private static async Task WriteHealthCheckResponse(HttpContext context, HealthReport report)
{
    context.Response.ContentType = "text/tab-separated-values; charset=utf-8";

    var strBldr = new StringBuilder(1024);
    using (var writer = new StringWriter(strBldr))
    {
        await writer.WriteLineAsync(string.Join('\t', "General", report.Status, $"{report.TotalDuration.TotalMilliseconds} ms"));
        foreach (var healthReportEntry in report.Entries)
        {
            await writer.WriteLineAsync(string.Join('\t', healthReportEntry.Key, healthReportEntry.Value.Status, healthReportEntry.Value.Description));
        }
    }

    await context.Response.WriteAsync(strBldr.ToString());
}

In dieser einfachen Implementierung wird der allgemeine Zustand und der Zustand der einzelnen Komponenten in Form von Tab-Separated-Values ausgegeben. Denkbar wäre auch eine einfache HTML-Seite oder das Zurückgeben von strukturierten Informationen im JSON-Format. Ein Beispiel hierzu ist in der Dokumentation enthalten.

Damit die Funktion auch zur Ausgabe verwendet wird, muss diese beim Mappen des Endpunkts angegeben werden:

endpoints.MapHealthChecks("/health", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions
{
    ResponseWriter = WriteHealthCheckResponse
}).RequireAuthorization("HealthCheckAuthorizationPolicy");

Anschließend wird folgende Ausgabe im Erfolgsfall erzeugt (Status code 200 OK):

General	Healthy	93,2117 ms
sqlserver	Healthy

Wenn wir den SQL Server abschalten, führt dies zu folgender Ausgabe (Status code 503 Service unavailable):

General	Unhealthy	14908,459 ms
sqlserver	Unhealthy

Fazit

Durch einen Health Check-Endpunkt wird man frühzeitig über Probleme in einer API oder einer verwendeten Komponente aufmerksam und kann frühzeitig reagieren. Die Erstellung des Endpunkts ist mit ASP.NET Core denkbar einfach. Die Dokumentation zeigt weitere Anpassungsmöglichkeiten, falls spezielle Anforderungen bestehen. Grundsätzlich gilt natürlich: auch ein einfacher Health Check-Endpunkt ist besser als keiner.

Ein kleiner Tipp zum Schluss: die Website uptimerobot.com bietet einen kostenfreien Plan, um einen Endpunkt regelmäßig zu prüfen und zu überwachen.

ASP.NET Core Health Checks Azure
Markus Wildgruber
Markus Wildgruber

Geschäftsführer

  • CloudArchitect
  • DeveloperCoach
  • DotNet
  • Angular
  • MongoDB