Monitorowanie kondycji

Napiwek

Ta zawartość jest fragmentem książki eBook, architektury mikrousług platformy .NET dla konteneryzowanych aplikacji platformy .NET dostępnych na platformie .NET Docs lub jako bezpłatnego pliku PDF, który można odczytać w trybie offline.

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

Monitorowanie kondycji może zezwalać na niemal rzeczywiste informacje o stanie kontenerów i mikrousług. Monitorowanie kondycji ma kluczowe znaczenie dla wielu aspektów działania mikrousług i jest szczególnie ważne, gdy orkiestratorzy wykonują częściowe uaktualnienia aplikacji w fazach, jak wyjaśniono później.

Aplikacje oparte na mikrousługach często używają pulsów lub kontroli kondycji, aby umożliwić monitorom wydajności, harmonogramom i orkiestratorom śledzenie wielu usług. Jeśli usługi nie mogą wysyłać sygnału "Jestem żywy", na żądanie lub zgodnie z harmonogramem, aplikacja może napotkać ryzyko podczas wdrażania aktualizacji lub może po prostu wykryć błędy za późno i nie być w stanie zatrzymać kaskadowych awarii, które mogą zakończyć się poważnymi awariami.

W typowym modelu usługi wysyłają raporty o ich stanie, a informacje te są agregowane w celu zapewnienia ogólnego widoku stanu kondycji aplikacji. Jeśli używasz orkiestratora, możesz podać informacje o kondycji klastrowi orkiestratora, aby klaster mógł działać odpowiednio. Jeśli zainwestujesz w wysokiej jakości raportowanie kondycji dostosowane dla aplikacji, możesz wykrywać i rozwiązywać problemy z uruchomioną aplikacją znacznie łatwiej.

Implementowanie kontroli kondycji w usługach ASP.NET Core

Podczas tworzenia mikrousługi ASP.NET Core lub aplikacji internetowej można użyć wbudowanej funkcji kontroli kondycji wydanej na platformie ASP .NET Core 2.2 (Microsoft.Extensions.Diagnostics.HealthChecks). Podobnie jak wiele funkcji ASP.NET Core, kontrole kondycji są dostarczane z zestawem usług i oprogramowania pośredniczącego.

Usługi kontroli kondycji i oprogramowanie pośredniczące są łatwe w użyciu i zapewniają możliwości umożliwiające sprawdzenie, czy jakikolwiek zasób zewnętrzny wymagany dla aplikacji (np. baza danych programu SQL Server lub zdalny interfejs API) działa prawidłowo. Jeśli używasz tej funkcji, możesz również zdecydować, co oznacza, że zasób jest w dobrej kondycji, jak wyjaśniamy później.

Aby efektywnie korzystać z tej funkcji, należy najpierw skonfigurować usługi w mikrousługach. Po drugie, potrzebna jest aplikacja frontonu, która wykonuje zapytania dotyczące raportów dotyczących kondycji. Ta aplikacja frontonu może być niestandardową aplikacją raportowania lub może być samą orkiestratorem, która może odpowiednio reagować na stany kondycji.

Używanie funkcji HealthChecks w mikrousługach zaplecza ASP.NET

W tej sekcji dowiesz się, jak zaimplementować funkcję HealthChecks w przykładowej aplikacji interfejsu API sieci Web ASP.NET Core 8.0 podczas korzystania z pakietu Microsoft.Extensions.Diagnostics.HealthChecks . Implementacja tej funkcji w mikrousługach na dużą skalę, takich jak eShopOnContainers, została wyjaśniona w następnej sekcji.

Aby rozpocząć, należy zdefiniować, co stanowi stan dobrej kondycji dla każdej mikrousługi. W przykładowej aplikacji definiujemy, że mikrousługa jest w dobrej kondycji, jeśli jej interfejs API jest dostępny za pośrednictwem protokołu HTTP, a powiązana z nią baza danych programu SQL Server jest również dostępna.

Na platformie .NET 8 z wbudowanymi interfejsami API można skonfigurować usługi, dodać kontrolę kondycji mikrousługi i jej zależną bazę danych programu SQL Server w następujący sposób:

// 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" });

W poprzednim kodzie services.AddHealthChecks() metoda konfiguruje podstawową kontrolę HTTP, która zwraca kod stanu 200 z wartością "W dobrej kondycji". AddCheck() Ponadto metoda rozszerzenia konfiguruje niestandardowySqlConnectionHealthCheck, który sprawdza kondycję powiązanej usługi SQL Database.

Metoda AddCheck() dodaje nową kontrolę kondycji z określoną nazwą i implementacją typu IHealthCheck. Można dodać wiele kontroli kondycji przy użyciu metody AddCheck, więc mikrousługa nie zapewni stanu "w dobrej kondycji", dopóki wszystkie testy nie będą w dobrej kondycji.

SqlConnectionHealthCheckjest klasą niestandardową, która implementuje IHealthCheckelement , który przyjmuje parametry połączenia jako parametr konstruktora i wykonuje proste zapytanie, aby sprawdzić, czy połączenie z bazą danych SQL zakończyło się pomyślnie. Zwraca wartość HealthCheckResult.Healthy() , jeśli zapytanie zostało wykonane pomyślnie i element FailureStatus z rzeczywistym wyjątkiem, gdy zakończy się niepowodzeniem.

// 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();
    }
}

Należy pamiętać, Select 1 że w poprzednim kodzie zapytanie służy do sprawdzania kondycji bazy danych. Aby monitorować dostępność mikrousług, koordynatorzy, tacy jak Kubernetes, okresowo wykonują testy kondycji, wysyłając żądania do testowania mikrousług. Ważne jest, aby zapewnić wydajne wykonywanie zapytań bazy danych, dzięki czemu te operacje są szybkie i nie powodują wyższego wykorzystania zasobów.

Na koniec dodaj oprogramowanie pośredniczące, które odpowiada na ścieżkę /hcadresu URL:

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

app.MapHealthChecks("/hc");

Po wywołaniu punktu końcowego <yourmicroservice>/hc uruchamia on wszystkie testy kondycji skonfigurowane w metodzie w AddHealthChecks() klasie Startup i wyświetla wynik.

Implementacja healthChecks w eShopOnContainers

Mikrousługi w usłudze eShopOnContainers polegają na wielu usługach w celu wykonania zadania. Na przykład Catalog.API mikrousługi z aplikacji eShopOnContainers zależą od wielu usług, takich jak Azure Blob Storage, SQL Server i RabbitMQ. W związku z tym ma kilka kontroli kondycji dodanych AddCheck() przy użyciu metody . W przypadku każdej usługi zależnej należy dodać niestandardową IHealthCheck implementację definiującą odpowiedni stan kondycji.

Projekt open source AspNetCore.Diagnostics.HealthChecks rozwiązuje ten problem, zapewniając niestandardowe implementacje kontroli kondycji dla każdego z tych usług przedsiębiorstwa, które są oparte na platformie .NET 8. Każda kontrola kondycji jest dostępna jako pojedynczy pakiet NuGet, który można łatwo dodać do projektu. eShopOnContainers wykorzystuje je szeroko we wszystkich swoich mikrousługach.

Na przykład w Catalog.API mikrousłudze dodano następujące pakiety NuGet:

Screenshot of the AspNetCore.Diagnostics.HealthChecks NuGet packages.

Rysunek 8–7. Niestandardowe kontrole kondycji zaimplementowane w interfejsie Catalog.API przy użyciu biblioteki AspNetCore.Diagnostics.HealthChecks

W poniższym kodzie implementacje kontroli kondycji są dodawane dla każdej usługi zależnej, a następnie skonfigurowano oprogramowanie pośredniczące:

// 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;
}

Na koniec dodaj oprogramowanie pośredniczące HealthCheck, aby nasłuchiwać punktu końcowego "/hc":

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

Wykonywanie zapytań dotyczących mikrousług w celu raportowania stanu kondycji

Po skonfigurowaniu kontroli kondycji zgodnie z opisem w tym artykule i masz mikrousługę uruchomioną na platformie Docker, możesz bezpośrednio sprawdzić w przeglądarce, jeśli jest w dobrej kondycji. Musisz opublikować port kontenera na hoście platformy Docker, aby uzyskać dostęp do kontenera za pośrednictwem zewnętrznego adresu IP hosta platformy Docker lub za pośrednictwem host.docker.internalmetody , jak pokazano na rysunku 8–8.

Screenshot of the JSON response returned by a health check.

Rysunek 8–8. Sprawdzanie stanu kondycji pojedynczej usługi z przeglądarki

W tym teście widać, że mikrousługa Catalog.API (uruchomiona na porcie 5101) jest w dobrej kondycji, zwracając informacje o stanie HTTP 200 i stan w formacie JSON. Usługa sprawdziła również kondycję zależności bazy danych programu SQL Server i RabbitMQ, więc sprawdzanie kondycji zgłosiło się jako w dobrej kondycji.

Korzystanie z watchdogów

Watchdog to oddzielna usługa, która może obserwować kondycję i ładować w usługach oraz zgłaszać kondycję mikrousług, wysyłając HealthChecks zapytanie do biblioteki wprowadzonej wcześniej. Może to pomóc w zapobieganiu błędom, które nie zostaną wykryte na podstawie widoku pojedynczej usługi. Watchdogs to również dobre miejsce do hostowania kodu, który może wykonywać akcje korygowania pod kątem znanych warunków bez interakcji użytkownika.

Przykład eShopOnContainers zawiera stronę internetową zawierającą przykładowe raporty dotyczące sprawdzania kondycji, jak pokazano na rysunku 8–9. Jest to najprostszy watchdog, który można mieć, ponieważ pokazuje tylko stan mikrousług i aplikacji internetowych w eShopOnContainers. Zwykle watchdog wykonuje również akcje w przypadku wykrycia stanów złej kondycji.

Na szczęście narzędzie AspNetCore.Diagnostics.HealthChecks udostępnia również pakiet NuGet AspNetCore.HealthChecks.UI , który może służyć do wyświetlania wyników sprawdzania kondycji ze skonfigurowanych identyfikatorów URI.

Screenshot of the Health Checks UI eShopOnContainers health statuses.

Rysunek 8–9. Przykładowy raport kontroli kondycji w aplikacji eShopOnContainers

Podsumowując, ta usługa watchdog wykonuje zapytania dotyczące punktu końcowego "/hc" każdej mikrousługi. Spowoduje to wykonanie wszystkich kontroli kondycji zdefiniowanych w nim i zwrócenie ogólnego stanu kondycji w zależności od wszystkich tych kontroli. HealthChecksUI jest łatwy w użyciu z kilkoma wpisami konfiguracji i dwoma wierszami kodu, które należy dodać do Startup.cs usługi watchdog.

Przykładowy plik konfiguracji interfejsu użytkownika sprawdzania kondycji:

// 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 plik, który dodaje 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");

Testy kondycji podczas korzystania z koordynatorów

Aby monitorować dostępność mikrousług, koordynatorzy, tacy jak Kubernetes i Service Fabric, okresowo wykonują testy kondycji, wysyłając żądania do testowania mikrousług. Gdy koordynator ustali, że usługa/kontener jest w złej kondycji, zatrzymuje kierowanie żądań do tego wystąpienia. Zwykle tworzy ono również nowe wystąpienie tego kontenera.

Na przykład większość koordynatorów może używać kontroli kondycji do zarządzania wdrożeniami bez przestojów. Tylko wtedy, gdy stan usługi/kontenera zmieni się na w dobrej kondycji, orkiestrator rozpocznie kierowanie ruchu do wystąpień usługi/kontenera.

Monitorowanie kondycji jest szczególnie ważne, gdy koordynator wykonuje uaktualnienie aplikacji. Niektóre usługi aktualizacji (takie jak Usługa Azure Service Fabric) w fazach — na przykład mogą aktualizować jedną piątą powierzchni klastra dla każdego uaktualnienia aplikacji. Zestaw węzłów uaktualnionych w tym samym czasie jest określany jako domena uaktualnienia. Po uaktualnieniu każdej domeny uaktualnienia i udostępnieniu jej użytkownikom domena uaktualnienia musi przejść testy kondycji przed przejściem wdrożenia do następnej domeny uaktualnienia.

Innym aspektem kondycji usługi jest raportowanie metryk z usługi. Jest to zaawansowana funkcja modelu kondycji niektórych koordynatorów, takich jak Service Fabric. Metryki są ważne podczas korzystania z koordynatora, ponieważ są używane do równoważenia użycia zasobów. Metryki mogą być również wskaźnikiem kondycji systemu. Na przykład może istnieć aplikacja, która ma wiele mikrousług, a każde wystąpienie zgłasza metrykę żądań na sekundę (RPS). Jeśli jedna usługa używa większej ilości zasobów (pamięci, procesora itp.) niż innej usługi, orkiestrator może przenosić wystąpienia usługi w klastrze, aby spróbować zachować nawet wykorzystanie zasobów.

Należy pamiętać, że usługa Azure Service Fabric udostępnia własny model monitorowania kondycji, który jest bardziej zaawansowany niż proste kontrole kondycji.

Zaawansowane monitorowanie: wizualizacja, analiza i alerty

Ostatnią częścią monitorowania jest wizualizowanie strumienia zdarzeń, raportowanie wydajności usługi i zgłaszanie alertów po wykryciu problemu. W tym aspekcie monitorowania można użyć różnych rozwiązań.

Możesz użyć prostych aplikacji niestandardowych pokazujących stan usług, takich jak strona niestandardowa wyświetlana podczas wyjaśniania aspNetCore.Diagnostics.HealthChecks. Możesz też użyć bardziej zaawansowanych narzędzi, takich jak Usługa Azure Monitor , aby zgłaszać alerty na podstawie strumienia zdarzeń.

Na koniec, jeśli przechowujesz wszystkie strumienie zdarzeń, możesz użyć usługi Microsoft Power BI lub innych rozwiązań, takich jak Kibana lub Splunk, aby zwizualizować dane.

Dodatkowe zasoby