Hälsoövervakning

Dricks

Det här innehållet är ett utdrag från eBook, .NET Microservices Architecture for Containerized .NET Applications, tillgängligt på .NET Docs eller som en kostnadsfri nedladdningsbar PDF som kan läsas offline.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Hälsoövervakning kan ge nästan realtidsinformation om tillståndet för dina containrar och mikrotjänster. Hälsoövervakning är avgörande för flera aspekter av mikrotjänster och är särskilt viktigt när orkestrerare utför partiella programuppgraderingar i faser, som beskrivs senare.

Mikrotjänstbaserade program använder ofta pulsslag eller hälsokontroller för att göra det möjligt för deras prestandaövervakare, schemaläggare och orkestrerare att hålla reda på de många olika tjänsterna. Om tjänster inte kan skicka någon form av "I'm alive"-signal, antingen på begäran eller enligt ett schema, kan ditt program utsättas för risker när du distribuerar uppdateringar, eller så kan det bara upptäcka fel för sent och inte kunna stoppa sammanhängande fel som kan hamna i stora avbrott.

I den typiska modellen skickar tjänster rapporter om deras status och den informationen aggregeras för att ge en övergripande vy över hälsotillståndet för ditt program. Om du använder en orkestrerare kan du ange hälsoinformation till orchestrator-klustret så att klustret kan agera i enlighet med detta. Om du investerar i hälsorapportering av hög kvalitet som är anpassad för ditt program kan du identifiera och åtgärda problem för ditt program som körs mycket enklare.

Implementera hälsokontroller i ASP.NET Core-tjänster

När du utvecklar en ASP.NET Core-mikrotjänst eller webbapp kan du använda den inbyggda funktionen för hälsokontroller som släpptes i ASP .NET Core 2.2 (Microsoft.Extensions.Diagnostics.HealthChecks). Liksom många ASP.NET Core-funktioner levereras hälsokontroller med en uppsättning tjänster och ett mellanprogram.

Hälsokontrolltjänster och mellanprogram är enkla att använda och tillhandahåller funktioner som gör att du kan kontrollera om någon extern resurs som behövs för ditt program (t.ex. en SQL Server-databas eller ett fjärranslutet API) fungerar korrekt. När du använder den här funktionen kan du också bestämma vad det innebär att resursen är felfri, som vi förklarar senare.

För att kunna använda den här funktionen effektivt måste du först konfigurera tjänster i dina mikrotjänster. För det andra behöver du ett klientdelsprogram som frågar efter hälsorapporterna. Klientdelsprogrammet kan vara ett anpassat rapporteringsprogram, eller så kan det vara en orkestrerare som kan reagera i enlighet med hälsotillstånden.

Använd funktionen HealthChecks i serverdelen ASP.NET mikrotjänster

I det här avsnittet får du lära dig hur du implementerar funktionen HealthChecks i ett exempel ASP.NET Core 8.0 Web API-program när du använder paketet Microsoft.Extensions.Diagnostics.HealthChecks . Implementeringen av den här funktionen i storskaliga mikrotjänster som eShopOnContainers förklaras i nästa avsnitt.

Till att börja med måste du definiera vad som utgör en felfri status för varje mikrotjänst. I exempelprogrammet definierar vi att mikrotjänsten är felfri om dess API är tillgängligt via HTTP och dess relaterade SQL Server-databas också är tillgänglig.

I .NET 8, med de inbyggda API:erna, kan du konfigurera tjänsterna, lägga till en hälsokontroll för mikrotjänsten och dess beroende SQL Server-databas på det här sättet:

// Program.cs from .NET 8 Web API sample

//...
// Registers required services for health checks
builder.Services.AddHealthChecks()
    // Add a health check for a SQL Server database
    .AddCheck(
        "OrderingDB-check",
        new SqlConnectionHealthCheck(builder.Configuration["ConnectionString"]),
        HealthStatus.Unhealthy,
        new string[] { "orderingdb" });

I föregående kod services.AddHealthChecks() konfigurerar metoden en grundläggande HTTP-kontroll som returnerar statuskoden 200 med "Felfri". Dessutom AddCheck() konfigurerar tilläggsmetoden en anpassad SqlConnectionHealthCheck som kontrollerar den relaterade SQL Database-hälsan.

Metoden AddCheck() lägger till en ny hälsokontroll med ett angivet namn och implementeringen av typen IHealthCheck. Du kan lägga till flera hälsokontroller med metoden AddCheck, så att en mikrotjänst inte ger statusen "felfri" förrän alla kontroller är felfria.

SqlConnectionHealthCheckär en anpassad klass som implementerar IHealthCheck, som tar en anslutningssträng som en konstruktorparameter och kör en enkel fråga för att kontrollera om anslutningen till SQL-databasen lyckas. Den returnerar HealthCheckResult.Healthy() om frågan har körts och en FailureStatus med det faktiska undantaget när den misslyckas.

// Sample SQL Connection Health Check
public class SqlConnectionHealthCheck : IHealthCheck
{
    private const string DefaultTestQuery = "Select 1";

    public string ConnectionString { get; }

    public string TestQuery { get; }

    public SqlConnectionHealthCheck(string connectionString)
        : this(connectionString, testQuery: DefaultTestQuery)
    {
    }

    public SqlConnectionHealthCheck(string connectionString, string testQuery)
    {
        ConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
        TestQuery = testQuery;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken))
    {
        using (var connection = new SqlConnection(ConnectionString))
        {
            try
            {
                await connection.OpenAsync(cancellationToken);

                if (TestQuery != null)
                {
                    var command = connection.CreateCommand();
                    command.CommandText = TestQuery;

                    await command.ExecuteNonQueryAsync(cancellationToken);
                }
            }
            catch (DbException ex)
            {
                return new HealthCheckResult(status: context.Registration.FailureStatus, exception: ex);
            }
        }

        return HealthCheckResult.Healthy();
    }
}

Observera att i föregående kod Select 1 är frågan som används för att kontrollera databasens hälsotillstånd. För att övervaka tillgängligheten för dina mikrotjänster utför orkestrerare som Kubernetes regelbundet hälsokontroller genom att skicka begäranden för att testa mikrotjänsterna. Det är viktigt att hålla databasfrågorna effektiva så att de här åtgärderna går snabbt och inte resulterar i en högre resursanvändning.

Lägg slutligen till ett mellanprogram som svarar på url-sökvägen /hc:

// Program.cs from .NET 8 Web Api sample

app.MapHealthChecks("/hc");

När slutpunkten <yourmicroservice>/hc anropas körs alla hälsokontroller som konfigureras i AddHealthChecks() metoden i klassen Startup och visar resultatet.

HealthChecks-implementering i eShopOnContainers

Mikrotjänster i eShopOnContainers förlitar sig på flera tjänster för att utföra sin uppgift. Mikrotjänsten från eShopOnContainers är till exempel Catalog.API beroende av många tjänster, till exempel Azure Blob Storage, SQL Server och RabbitMQ. Därför har flera hälsokontroller lagts till med hjälp av AddCheck() metoden. För varje beroende tjänst måste en anpassad IHealthCheck implementering som definierar dess respektive hälsostatus läggas till.

Projektet AspNetCore.Diagnostics.HealthChecks med öppen källkod löser problemet genom att tillhandahålla anpassade implementeringar av hälsokontroller för var och en av dessa företagstjänster, som bygger på .NET 8. Varje hälsokontroll är tillgänglig som ett enskilt NuGet-paket som enkelt kan läggas till i projektet. eShopOnContainers använder dem i stor utsträckning i alla sina mikrotjänster.

I mikrotjänsten har till exempel Catalog.API följande NuGet-paket lagts till:

Screenshot of the AspNetCore.Diagnostics.HealthChecks NuGet packages.

Bild 8-7. Anpassade hälsokontroller implementerade i Catalog.API med AspNetCore.Diagnostics.HealthChecks

I följande kod läggs implementeringarna för hälsokontroll till för varje beroende tjänst och sedan konfigureras mellanprogrammet:

// Extension method from Catalog.api microservice
//
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
{
    var accountName = configuration.GetValue<string>("AzureStorageAccountName");
    var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");

    var hcBuilder = services.AddHealthChecks();

    hcBuilder
        .AddSqlServer(
            configuration["ConnectionString"],
            name: "CatalogDB-check",
            tags: new string[] { "catalogdb" });

    if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey))
    {
        hcBuilder
            .AddAzureBlobStorage(
                $"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net",
                name: "catalog-storage-check",
                tags: new string[] { "catalogstorage" });
    }
    if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
    {
        hcBuilder
            .AddAzureServiceBusTopic(
                configuration["EventBusConnection"],
                topicName: "eshop_event_bus",
                name: "catalog-servicebus-check",
                tags: new string[] { "servicebus" });
    }
    else
    {
        hcBuilder
            .AddRabbitMQ(
                $"amqp://{configuration["EventBusConnection"]}",
                name: "catalog-rabbitmqbus-check",
                tags: new string[] { "rabbitmqbus" });
    }

    return services;
}

Lägg slutligen till HealthCheck-mellanprogrammet för att lyssna på slutpunkten "/hc":

// HealthCheck middleware
app.UseHealthChecks("/hc", new HealthCheckOptions()
{
    Predicate = _ => true,
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

Fråga dina mikrotjänster för att rapportera om deras hälsostatus

När du har konfigurerat hälsokontroller enligt beskrivningen i den här artikeln och mikrotjänsten körs i Docker kan du direkt kontrollera från en webbläsare om den är felfri. Du måste publicera containerporten i Docker-värden så att du kan komma åt containern via den externa Docker-värd-IP-adressen eller via host.docker.internal, enligt bild 8–8.

Screenshot of the JSON response returned by a health check.

Bild 8-8. Kontrollera hälsostatus för en enskild tjänst från en webbläsare

I det testet kan du se att Catalog.API mikrotjänsten (som körs på port 5101) är felfri och returnerar HTTP-status 200 och statusinformation i JSON. Tjänsten kontrollerade också hälsotillståndet för dess SQL Server-databasberoende och RabbitMQ, så hälsokontrollen rapporterade sig själv som felfri.

Använda vakthundar

En vakthund är en separat tjänst som kan övervaka hälsa och belastning över tjänster och rapportera hälsa om mikrotjänsterna genom att fråga med HealthChecks biblioteket som introducerades tidigare. Detta kan hjälpa till att förhindra fel som inte identifieras baserat på vyn för en enda tjänst. Vakthundar är också ett bra ställe att vara värd för kod som kan utföra reparationsåtgärder för kända villkor utan användarinteraktion.

Exemplet eShopOnContainers innehåller en webbsida som visar exempel på hälsokontrollrapporter, enligt bild 8–9. Det här är den enklaste vakthunden du kan ha eftersom den bara visar tillståndet för mikrotjänster och webbprogram i eShopOnContainers. Vanligtvis vidtar en vakthund också åtgärder när den identifierar feltillstånd.

Lyckligtvis tillhandahåller AspNetCore.Diagnostics.HealthChecks även NuGet-paketet AspNetCore.HealthChecks.UI som kan användas för att visa hälsokontrollresultaten från de konfigurerade URI:erna.

Screenshot of the Health Checks UI eShopOnContainers health statuses.

Bild 8-9. Exempel på hälsokontrollrapport i eShopOnContainers

Sammanfattningsvis frågar den här övervakningstjänsten varje mikrotjänsts slutpunkt "/hc". Detta kör alla hälsokontroller som definierats i den och returnerar ett övergripande hälsotillstånd beroende på alla dessa kontroller. HealthChecksUI är enkelt att använda med några konfigurationsposter och två kodrader som måste läggas till i Startup.cs för övervakningstjänsten.

Exempelkonfigurationsfil för användargränssnittet för hälsokontroll:

// Configuration
{
  "HealthChecksUI": {
    "HealthChecks": [
      {
        "Name": "Ordering HTTP Check",
        "Uri": "http://host.docker.internal:5102/hc"
      },
      {
        "Name": "Ordering HTTP Background Check",
        "Uri": "http://host.docker.internal:5111/hc"
      },
      //...
    ]}
}

Program.cs fil som lägger till HealthChecksUI:

// Program.cs from WebStatus(Watch Dog) service
//
// Registers required services for health checks
builder.Services.AddHealthChecksUI();
// build the app, register other middleware
app.UseHealthChecksUI(config => config.UIPath = "/hc-ui");

Hälsokontroller när du använder orchestrators

För att övervaka tillgängligheten för dina mikrotjänster utför orkestrerare som Kubernetes och Service Fabric regelbundet hälsokontroller genom att skicka begäranden för att testa mikrotjänsterna. När en orkestrerare fastställer att en tjänst/container inte är felfri slutar den dirigera begäranden till den instansen. Den skapar också vanligtvis en ny instans av containern.

De flesta orkestrerare kan till exempel använda hälsokontroller för att hantera distributioner med noll driftstopp. Endast när statusen för en tjänst/container ändras till felfri kommer orkestratorn att börja dirigera trafik till tjänst-/containerinstanser.

Hälsoövervakning är särskilt viktigt när en orkestrerare utför en programuppgradering. Vissa orkestrerare (till exempel Azure Service Fabric) uppdaterar tjänster i faser, till exempel kan de uppdatera en femtedel av klusterytan för varje programuppgradering. Den uppsättning noder som uppgraderas samtidigt kallas för en uppgraderingsdomän. När varje uppgraderingsdomän har uppgraderats och är tillgänglig för användare måste uppgraderingsdomänen klara hälsokontroller innan distributionen flyttas till nästa uppgraderingsdomän.

En annan aspekt av tjänstens hälsa är att rapportera mått från tjänsten. Det här är en avancerad funktion i hälsomodellen för vissa orkestratorer, till exempel Service Fabric. Mått är viktiga när du använder en orkestrerare eftersom de används för att balansera resursanvändning. Mått kan också vara en indikator på systemets hälsa. Du kan till exempel ha ett program som har många mikrotjänster, och varje instans rapporterar ett RPS-mått (requests-per-second). Om en tjänst använder fler resurser (minne, processor osv.) än en annan tjänst kan orkestreraren flytta runt tjänstinstanser i klustret för att försöka upprätthålla en jämn resursanvändning.

Observera att Azure Service Fabric tillhandahåller en egen hälsoövervakningsmodell, som är mer avancerad än enkla hälsokontroller.

Avancerad övervakning: visualisering, analys och aviseringar

Den sista delen av övervakningen är att visualisera händelseströmmen, rapportera tjänstprestanda och aviseringar när ett problem identifieras. Du kan använda olika lösningar för den här övervakningsaspekten.

Du kan använda enkla anpassade program som visar tillståndet för dina tjänster, som den anpassade sidan som visas när du förklarar AspNetCore.Diagnostics.HealthChecks. Eller så kan du använda mer avancerade verktyg som Azure Monitor för att skapa aviseringar baserat på händelseströmmen.

Om du lagrar alla händelseströmmar kan du slutligen använda Microsoft Power BI eller andra lösningar som Kibana eller Splunk för att visualisera data.

Ytterligare resurser