Integritätsprüfungen in ASP.NET Core
Von Glenn Condron und Jürgen Gutsch
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
ASP.NET Core bietet Middleware für Integritätsprüfungen und Bibliotheken für die Berichterstellung für Komponenten der App-Infrastruktur.
Integritätsprüfungen werden von einer App als HTTP-Endpunkte verfügbar gemacht. Endpunkte für die Integritätsprüfung können für verschiedene Echtzeitüberwachungsszenarien konfiguriert werden:
- Integritätstests können von Containerorchestratoren und Lastenausgleichsmodulen verwendet werden, um den Status einer App zu überprüfen. Ein Containerorchestrator kann z.B. auf eine fehlerhafte Integritätsprüfung reagieren, indem die Ausführung einer Bereitstellung angehalten oder ein Container neu gestartet wird. Ein Lastenausgleichsmodul kann auf eine fehlerhafte App reagieren, indem Datenverkehr von der fehlerhaften zu einer fehlerfreien Instanz umgeleitet wird.
- Die Nutzung von Arbeitsspeicher, Datenträgern und anderen physischen Serverressourcen kann auf einen fehlerfreien Status überwacht werden.
- Integritätsprüfungen können die Abhängigkeiten einer App testen, wie z.B. Datenbanken und externe Dienstendpunkte, um Verfügbarkeit und normale Funktionsweise zu bestätigen.
Integritätsprüfungen werden in der Regel mit einem externen Überwachungsdienst oder Containerorchestrator verwendet, um den Status einer App zu überprüfen. Bevor Sie Integritätsprüfungen zu einer App hinzufügen, entscheiden Sie, welches Überwachungssystem verwendet werden soll. Das Überwachungssystem bestimmt, welche Arten von Integritätsprüfungen erstellt und wie die jeweiligen Endpunkte konfiguriert werden müssen.
Grundlegender Integritätstest
In vielen Apps genügt zur Ermittlung des App-Status eine grundlegende Integritätstestkonfiguration, die die Verfügbarkeit der App für die Verarbeitung von Anforderungen (Lebendigkeit) meldet.
Die grundlegende Konfiguration registriert Integritätsprüfungsdienste und ruft die Middleware für Integritätsprüfungen auf, damit diese an einem URL-Endpunkt mit dem Integritätsstatus antwortet. Standardmäßig werden keine spezifischen Integritätsprüfungen registriert, um eine bestimmte Abhängigkeit oder ein bestimmtes Subsystem zu testen. Die App wird als fehlerfrei angesehen, wenn sie an der URL des Integritätsendpunkts antworten kann. Der Standardantwortwriter schreibt HealthStatus als Klartextantwort an den Client. HealthStatus
ist HealthStatus.Healthy, HealthStatus.Degraded oder HealthStatus.Unhealthy.
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Program.cs
. Erstellen Sie einen Integritätsprüfungsendpunkt durch Aufrufen von MapHealthChecks.
Im folgenden Beispiel wird ein Integritätsprüfungsendpunkt unter /healthz
erstellt:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/healthz");
app.Run();
Docker HEALTHCHECK
Docker bietet eine integrierte HEALTHCHECK
-Direktive, mit der Sie den Status einer App überprüfen können, die die grundlegende Konfiguration für Integritätsprüfungen verwendet:
HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit
Das vorherige Beispiel verwendet curl
, um eine HTTP-Anforderung an den Integritätsprüfungsendpunkt bei /healthz
auszugeben. curl
ist nicht in den .NET Linux-Containerimages enthalten, kann aber hinzugefügt werden, indem das erforderliche Paket in der Dockerfile installiert wird. Container, die auf Alpine Linux basierende Images verwenden, können das enthaltene wget
anstelle von curl
verwenden.
Erstellen von Integritätsprüfungen
Integritätsprüfungen werden durch Implementieren der IHealthCheck-Schnittstelle erstellt. Die CheckHealthAsync-Methode gibt ein HealthCheckResult zurück, das die Integrität als Healthy
, Degraded
oder Unhealthy
angibt. Das Ergebnis wird als Klartextantwort mit einem konfigurierbaren Statuscode geschrieben. Die Konfiguration wird im Abschnitt Integritätsprüfungsoptionen beschrieben. HealthCheckResult kann auch optionale Schlüssel-Wert-Paare zurückgeben.
Das folgende Beispiel veranschaulicht das Layout einer Integritätsprüfung:
public class SampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
Die Integritätsprüfungslogik wird in der CheckHealthAsync-Methode platziert. Im vorherigen Beispiel wird die Dummyvariable isHealthy
auf true
festgelegt. Wenn der Wert von isHealthy
auf false
festgelegt ist, wird der HealthCheckRegistration.FailureStatus-Status zurückgegeben.
Wenn CheckHealthAsync während der Überprüfung eine Ausnahme auslöst, wird ein neues Element HealthReportEntry zurückgegeben, dessen HealthReportEntry.Status auf FailureStatus festgelegt ist. Dieser Status ist definiert durch AddCheck (weitere Informationen finden Sie im Abschnitt Registrieren von Diensten zur Integritätsprüfung) und enthält die innere Ausnahme, die den Prüfungsfehler verursacht hat. Description ist auf die Meldung der Ausnahme festgelegt.
Registrieren von Integritätsprüfungsdiensten
Rufen Sie AddCheck in Program.cs
auf, um einen Integritätsprüfungsdienst zu registrieren:
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>("Sample");
Die in der folgenden Abbildung gezeigte AddCheck-Überladung legt den Fehlerstatus (HealthStatus) fest, der angegeben werden soll, wenn die Integritätsprüfung einen Fehler meldet. Wenn der Fehlerstatus auf null
(Standardwert) festgelegt ist, wird HealthStatus.Unhealthy gemeldet. Diese Überladung ist ein nützliches Szenario für Bibliotheksersteller: Bei einem Integritätsprüfungsfehler wird der durch die Bibliothek angegebene Fehlerstatus von der App erzwungen, wenn die Implementierung der Integritätsprüfung die Einstellung berücksichtigt.
Tags können zum Filtern von Integritätsprüfungen verwendet werden. Tags werden im Abschnitt Filtern von Integritätsprüfungen beschrieben.
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" });
AddCheck kann auch eine Lambdafunktion ausführen. Im folgenden Beispiel gibt die Integritätsprüfung immer ein fehlerfreies Ergebnis zurück:
builder.Services.AddHealthChecks()
.AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));
Rufen Sie AddTypeActivatedCheck auf, um Argumente an die Implementierung einer Integritätsprüfung zu übergeben. Im folgenden Beispiel akzeptiert eine typaktivierte Integritätsprüfung in ihrem Konstruktor eine ganze Zahl und eine Zeichenfolge:
public class SampleHealthCheckWithArgs : IHealthCheck
{
private readonly int _arg1;
private readonly string _arg2;
public SampleHealthCheckWithArgs(int arg1, string arg2)
=> (_arg1, _arg2) = (arg1, arg2);
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
// ...
return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
}
}
Um die vorherige Integritätsprüfung zu registrieren, rufen Sie AddTypeActivatedCheck
mit der ganzen Zahl und der Zeichenfolge auf, die als Argumente übergeben werden:
builder.Services.AddHealthChecks()
.AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" },
args: new object[] { 1, "Arg" });
Verwenden von Integritätsprüfungsrouting
Rufen Sie in Program.cs
auf der Endpunkterstellung mit der Endpunkt-URL oder dem relativen Pfad MapHealthChecks
auf:
app.MapHealthChecks("/healthz");
Anfordern des Hosts
Rufen Sie RequireHost
auf, um einen oder mehrere zugelassene Hosts für den Integritätsprüfungs-Endpunkt anzugeben. Hosts sollten Unicode anstelle von Punycode verwenden und können einen Port enthalten. Wenn keine Sammlung bereitgestellt wird, wird jeder Host akzeptiert:
app.MapHealthChecks("/healthz")
.RequireHost("www.contoso.com:5001");
Um den Integritätsprüfungsendpunkt so einzuschränken, dass er nur an einem bestimmten Port antwortet, geben Sie beim Aufruf von RequireHost
einen Port an. Dieser Ansatz wird normalerweise in einer Containerumgebung verfolgt, um einen Port für Überwachungsdienste verfügbar zu machen:
app.MapHealthChecks("/healthz")
.RequireHost("*:5001");
Warnung
Die APIs, die auf dem Hostheader basieren, z. B. HttpRequest.Host und RequireHost, sind potenziellem Spoofing durch Clients ausgesetzt.
Verwenden Sie einen der folgenden Ansätze, um Host- und Portspoofing zu verhindern:
- Verwenden Sie HttpContext.Connection (ConnectionInfo.LocalPort), wobei die Ports aktiviert sind.
- Verwenden Sie die Hostfilterung.
Um zu verhindern, dass nicht autorisierte Clients den Port spoofen, rufen Sie RequireAuthorization auf:
app.MapHealthChecks("/healthz")
.RequireHost("*:5001")
.RequireAuthorization();
Weitere Informationen finden Sie unter Hostabgleich in Routen mit RequireHost.
Anfordern der Autorisierung
Rufen Sie RequireAuthorization auf, um die Autorisierungsmiddleware auf dem Integritätsprüfungs-Anforderungsendpunkt auszuführen. Eine RequireAuthorization
-Überladung akzeptiert eine oder mehrere Autorisierungsrichtlinien. Wenn keine Richtlinie bereitgestellt wird, wird die standardmäßige Autorisierungsrichtlinie verwendet:
app.MapHealthChecks("/healthz")
.RequireAuthorization();
Aktivieren ursprungsübergreifender Anforderungen (CORS)
Obwohl das manuelle Ausführen von Integritätsprüfungen über einen Browser kein gängiges Szenario ist, kann CORS-Middleware durch Aufrufen von RequireCors
für Integritätsprüfungsendpunkte aktiviert werden. Eine RequireCors
-Überladung akzeptiert einen CORS-Richtliniengenerator-Delegaten (CorsPolicyBuilder
) oder einen Richtliniennamen. Weitere Informationen finden Sie unter Aktivieren ursprungsübergreifender Anforderungen (Cross-Origin Requests, CORS) in ASP.NET Core.
Optionen für die Integritätsprüfung
HealthCheckOptions ermöglichen die Anpassung des Verhaltens von Integritätsprüfungen:
- Filtern von Integritätsprüfungen
- Anpassen des HTTP-Statuscodes
- Unterdrücken von Cacheheadern
- Anpassen der Ausgabe
Filtern von Integritätsprüfungen
Standardmäßig führt die Middleware für Integritätsprüfungen alle registrierten Integritätsprüfungen aus. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die einen booleschen Wert an die Option Predicate zurückgibt.
Im folgenden Beispiel werden die Integritätsprüfungen so gefiltert, dass nur die mit sample
gekennzeichneten ausgeführt werden:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});
Anpassen des HTTP-Statuscodes
Verwenden Sie ResultStatusCodes, um die Zuordnung des Integritätsstatus zu HTTP-Statuscodes anzupassen. Die folgenden StatusCodes-Zuweisungen stellen die von der Middleware verwendeten Standardwerte dar. Ändern Sie die Statuscodewerte so, dass sie Ihren Anforderungen entsprechen:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
Unterdrücken von Cacheheadern
AllowCachingResponses steuert, ob die Middleware für Integritätsprüfungen einer Testantwort HTTP-Header hinzufügt, um das Zwischenspeichern von Antworten zu verhindern. Wenn der Wert false
(Standard) lautet, legt die Middleware die Header Cache-Control
, Expires
und Pragma
fest oder überschreibt sie, um eine Zwischenspeicherung der Antworten zu verhindern. Wenn der Wert true
lautet, ändert die Middleware die Cacheheader der Antwort nicht:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
AllowCachingResponses = true
});
Anpassen der Ausgabe
Um die Ausgabe eines Integritätsprüfungsberichts anzupassen, legen Sie die Eigenschaft HealthCheckOptions.ResponseWriter für einen Delegaten fest, der die Antwort schreibt:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResponseWriter = WriteResponse
});
Der Standarddelegat schreibt eine minimale Klartextantwort mit dem Zeichenfolgenwert HealthReport.Status
. Der folgende benutzerdefinierte Delegat gibt eine benutzerdefinierte JSON-Antwort mithilfe von System.Text.Json aus:
private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions { Indented = true };
using var memoryStream = new MemoryStream();
using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
{
jsonWriter.WriteStartObject();
jsonWriter.WriteString("status", healthReport.Status.ToString());
jsonWriter.WriteStartObject("results");
foreach (var healthReportEntry in healthReport.Entries)
{
jsonWriter.WriteStartObject(healthReportEntry.Key);
jsonWriter.WriteString("status",
healthReportEntry.Value.Status.ToString());
jsonWriter.WriteString("description",
healthReportEntry.Value.Description);
jsonWriter.WriteStartObject("data");
foreach (var item in healthReportEntry.Value.Data)
{
jsonWriter.WritePropertyName(item.Key);
JsonSerializer.Serialize(jsonWriter, item.Value,
item.Value?.GetType() ?? typeof(object));
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
return context.Response.WriteAsync(
Encoding.UTF8.GetString(memoryStream.ToArray()));
}
Die Integritätsprüfungs-API bietet keine integrierte Unterstützung für komplexe JSON-Rückgabeformate, da das Format für Ihre Überwachungssystemauswahl spezifisch ist. Passen Sie die Antwort in den vorangehenden Beispielen nach Bedarf an. Weitere Informationen zur JSON-Serialisierung mit System.Text.Json
finden Sie unter Serialisieren und Deserialisieren von JSON in .NET.
Datenbanktest
Eine Integritätsprüfung kann eine Datenbankabfrage angeben, die als boolescher Test ausgeführt wird, um zu ermitteln, ob die Datenbank normal reagiert.
AspNetCore.Diagnostics.HealthChecks
, eine Integritätsprüfungsbibliothek für ASP.NET Core-Apps, enthält eine Integritätsprüfung, die für eine SQL Server-Datenbank ausgeführt wird. AspNetCore.Diagnostics.HealthChecks
führt eine SELECT 1
-Abfrage in der Datenbank aus, um zu bestätigen, dass die Verbindung mit der Datenbank fehlerfrei ist.
Warnung
Wenn Sie die Datenbankverbindung mithilfe einer Abfrage überprüfen, wählen Sie eine Abfrage aus, die eine schnelle Antwort zurückgibt. Bei einer Abfrage besteht immer das Risiko, dass die Datenbank überladen und ihre Leistung beeinträchtigt wird. In den meisten Fällen ist es nicht notwendig, eine Testabfrage auszuführen. Es genügt zumeist, einfach erfolgreich eine Verbindung mit der Datenbank herzustellen. Wenn Sie eine Abfrage ausführen müssen, wählen Sie eine einfache SELECT-Abfrage aus, wie z.B. SELECT 1
.
Um diese SQL Server-Integritätsprüfung zu verwenden, fügen Sie einen Paketverweis auf das NuGet-Paket AspNetCore.HealthChecks.SqlServer
ein. Im folgenden Beispiel wird die SQL Server-Integritätsüberprüfung registriert:
var conStr = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(conStr))
{
throw new InvalidOperationException(
"Could not find a connection string named 'DefaultConnection'.");
}
builder.Services.AddHealthChecks()
.AddSqlServer(conStr);
Hinweis
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Entity Framework Core-DbContext-Test
Die DbContext
-Überprüfung bestätigt, dass die App mit der Datenbank kommunizieren kann, die für einen EF Core-DbContext
konfiguriert wurde. Die DbContext
Überprüfung wird in Apps unterstützt, für die gilt:
- In ihnen wird Entity Framework Core (EF Core) verwendet.
- Fügen Sie einen Verweis auf das NuGet-Paket
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
ein.
AddDbContextCheck registriert eine Integritätsprüfung für einen DbContext. DbContext
wird der Methode als TContext
bereitgestellt. Eine Überladung ist verfügbar, um den Fehlerstatus, Tags sowie eine benutzerdefinierte Testabfrage zu konfigurieren.
Standardmäßig:
- Der
DbContextHealthCheck
ruft dieCanConnectAsync
-Methode von EF Core auf. Sie können festlegen, welcher Vorgang ausgeführt wird, wenn die Integrität mitAddDbContextCheck
-Methodenüberladungen überprüft wird. - Der Name der Integritätsprüfung ist der Name des
TContext
-Typs.
Im folgenden Beispiel werden ein DbContext
und ein zugeordneter DbContextHealthCheck
registriert:
builder.Services.AddDbContext<SampleDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddHealthChecks()
.AddDbContextCheck<SampleDbContext>();
Separate Tests für Bereitschaft und Lebendigkeit
In einigen Hostingszenarien wird ein Integritätsprüfungspaar verwendet, mit dem zwischen zwei App-Status unterschieden wird:
- Bereitschaft gibt an, ob die App ordnungsgemäß ausgeführt wird, aber nicht für den Empfang von Anforderungen bereit ist.
- Livetest gibt an, ob eine App abgestürzt ist und neu gestartet werden muss.
Betrachten Sie das folgende Beispiel: Eine App muss eine große Konfigurationsdatei herunterladen, bevor sie für die Verarbeitung von Anforderungen bereit ist. Wir möchten nicht, dass die App neu gestartet wird, wenn der erste Download fehlschlägt, da die App mehrmals versuchen kann, die Datei herunterzuladen. Wir verwenden einen Livetest, um den Livezustand des Prozesses zu beschreiben. Weitere Überprüfungen erfolgen nicht. Außerdem soll verhindert werden, dass Anforderungen an die App gesendet werden, bevor die Konfigurationsdatei erfolgreich heruntergeladen wurde. Wir verwenden einen Bereitschaftstest, um den Status "nicht bereit" anzugeben, bis der Download erfolgreich durchgeführt wurde und die App für den Empfang von Anforderungen bereit ist.
Die folgende Hintergrundaufgabe simuliert einen Startprozess, der ungefähr 15 Sekunden dauert. Nach Abschluss des Vorgangs legt die Aufgabe die StartupHealthCheck.StartupCompleted
-Eigenschaft auf TRUE fest:
public class StartupBackgroundService : BackgroundService
{
private readonly StartupHealthCheck _healthCheck;
public StartupBackgroundService(StartupHealthCheck healthCheck)
=> _healthCheck = healthCheck;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Simulate the effect of a long-running task.
await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);
_healthCheck.StartupCompleted = true;
}
}
StartupHealthCheck
meldet die Beendigung der lang ausgeführten Startaufgabe und macht die Eigenschaft StartupCompleted
verfügbar, die vom Hintergrunddienst festgelegt wird:
public class StartupHealthCheck : IHealthCheck
{
private volatile bool _isReady;
public bool StartupCompleted
{
get => _isReady;
set => _isReady = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
if (StartupCompleted)
{
return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
}
return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
}
}
Die Integritätsprüfung wird mit AddCheck zusammen mit dem gehosteten Dienst in Program.cs
registriert. Da der gehostete Dienst die Eigenschaft in der Integritätsprüfung festlegen muss, wird die Integritätsprüfung ebenfalls im Dienstcontainer als Singleton registriert:
builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();
builder.Services.AddHealthChecks()
.AddCheck<StartupHealthCheck>(
"Startup",
tags: new[] { "ready" });
Um zwei verschiedene Integritätsprüfungsendpunkte zu erstellen, rufen Sie MapHealthChecks
zweimal auf:
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
Predicate = _ => false
});
Im vorherigen Beispiel werden die folgenden Integritätsprüfungsendpunkte erstellt:
/healthz/ready
für die Bereitschaftsprüfung. Die Bereitschaftsprüfung filtert Integritätsprüfungen heraus, die mitready
gekennzeichnet sind./healthz/live
für die Lebendigkeitsprüfung. Die Liveüberprüfung filtert alle Integritätsprüfungen heraus, indemfalse
im Delegaten HealthCheckOptions.Predicate zurückgegeben wird. Weitere Informationen zum Filtern von Integritätsprüfungen finden Sie unter Filtern von Integritätsprüfungen in diesem Artikel.
Bevor die Startaufgabe abgeschlossen ist, meldet der Endpunkt /healthz/ready
den Status Unhealthy
. Bevor die Startaufgabe abgeschlossen ist, meldet dieser Endpunkt den Status Healthy
. Der Endpunkt /healthz/live
schließt alle Überprüfungen aus und meldet für alle Aufrufe den Status Healthy
.
Kubernetes-Beispiel
Die Verwendung von Bereitschafts- und Lebendigkeitstests ist in Umgebungen wie Kubernetes sehr nützlich. In Kubernetes muss eine App möglicherweise zeitaufwendige Startaufgaben ausführen, bevor sie Anforderungen wie z. B. das Testen der Verfügbarkeit der zugrunde liegenden Datenbank erfüllt. Durch Verwendung separater Überprüfungen kann der Orchestrator unterscheiden, ob eine App funktioniert, aber noch nicht bereit ist, oder ob die App nicht gestartet wurde. Weitere Informationen zu Bereitschafts- und Lebendigkeitstests in Kubernetes finden Sie in der Kubernetes-Dokumentation unter Configure Liveness and Readiness Probes (Konfigurieren von Lebendigkeits- und Bereitschaftstests).
Das folgende Beispiel veranschaulicht die Konfiguration eines Bereitschaftstests in Kubernetes:
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /healthz/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
Verteilen einer Integritätsprüfungsbibliothek
So verteilen Sie eine Integritätsprüfung als Bibliothek:
Schreiben Sie eine Integritätsprüfung, die die IHealthCheck-Schnittstelle als eigenständige Klasse implementiert. Die Klasse kann Abhängigkeitsinjektion (Dependency Injection, DI), Typaktivierung und benannte Optionen verwenden, um auf Konfigurationsdaten zuzugreifen.
Schreiben Sie eine Erweiterungsmethode mit Parametern, die von der nutzenden App in ihrer
Program.cs
-Methode aufgerufen werden. Betrachten Sie das folgende Beispiel einer Integritätsprüfung, diearg1
undarg2
als Konstruktorparameter akzeptiert:public SampleHealthCheckWithArgs(int arg1, string arg2) => (_arg1, _arg2) = (arg1, arg2);
Die vorherige Signatur gibt an, dass die Integritätsprüfung benutzerdefinierte Daten benötigt, um die Prüflogik der Integritätsprüfung zu verarbeiten. Die Daten werden für den Delegaten bereitgestellt, der zum Erstellen der Integritätsprüfungsinstanz verwendet wird, wenn die Integritätsprüfung bei einer Erweiterungsmethode registriert wird. Im folgenden Beispiel gibt der Aufrufer Folgendes an:
arg1
: ein integer-Datenpunkt für die Integritätsprüfung.arg2
: ein Zeichenfolgenargument für die Integritätsprüfung.name
: ein optionaler Name der Integritätsprüfung. Fallsnull
, wird ein Standardwert verwendet.failureStatus
: ein optionales Element HealthStatus, das bei einem Fehlerstatus gemeldet wird. Wenn der Wertnull
ist, wird HealthStatus.Unhealthy verwendet.tags
: eine optionaleIEnumerable<string>
-Sammlung von Tags.
public static class SampleHealthCheckBuilderExtensions { private const string DefaultName = "Sample"; public static IHealthChecksBuilder AddSampleHealthCheck( this IHealthChecksBuilder healthChecksBuilder, int arg1, string arg2, string? name = null, HealthStatus? failureStatus = null, IEnumerable<string>? tags = default) { return healthChecksBuilder.Add( new HealthCheckRegistration( name ?? DefaultName, _ => new SampleHealthCheckWithArgs(arg1, arg2), failureStatus, tags)); } }
Herausgeber der Integritätsprüfung
Wenn dem Dienstcontainer ein IHealthCheckPublisher hinzugefügt wird, führt das Integritätsprüfungssystem Ihre Integritätsprüfungen regelmäßig aus und ruft PublishAsync mit dem Ergebnis auf. Dieser Prozess ist nützlich in einem Szenario mit pushbasiertem Integritätsüberwachungssystem, in dem jeder Prozess das Überwachungssystem regelmäßig aufrufen muss, um Integrität zu bestimmen.
HealthCheckPublisherOptions ermöglichen Ihnen, Folgendes festzulegen:
- Delay: Hierbei handelt es sich um die angewendete anfängliche Verzögerung zwischen dem Start der App und der Ausführung von IHealthCheckPublisher-Instanzen. Die Verzögerung wird einmal beim Start angewendet und gilt nicht für spätere Iterationen. Der Standardwert beträgt fünf Sekunden.
- Period: Hierbei handelt es sich um die Dauer der Ausführung von IHealthCheckPublisher. Der Standardwert ist 30 Sekunden.
- Predicate: Wenn der Wert für Predicate
null
ist (Standard), führt der Veröffentlichungsdienst für die Integritätsprüfung alle registrierten Integritätsprüfungen durch. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die die Menge der Prüfungen filtert. Das Prädikat wird in jedem Zeitraum ausgewertet. - Timeout: Hierbei handelt es sich um das Zeitlimit für die Ausführung der Integritätsprüfungen für alle IHealthCheckPublisher-Instanzen. Verwenden Sie InfiniteTimeSpan zur Ausführung ohne Timeout. Der Standardwert ist 30 Sekunden.
Das folgende Beispiel veranschaulicht das Layout eines Integritätsprüfungsherausgebers:
public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
// ...
}
else
{
// ...
}
return Task.CompletedTask;
}
}
Die HealthCheckPublisherOptions-Klasse stellt Eigenschaften zum Konfigurieren des Verhaltens des Integritätsprüfungsherausgebers bereit.
Im folgenden Beispiel wird ein Integritätsprüfungsherausgeber als Singleton registriert und HealthCheckPublisherOptions konfiguriert:
builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});
builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();
AspNetCore.Diagnostics.HealthChecks
:
- Enthält Herausgeber für verschiedene Systeme, einschließlich Application Insights.
- Wird von Microsoft nicht verwaltet oder unterstützt.
Individuelle Integritätsprüfungen
Delay
und Period
können jeweils einzeln für HealthCheckRegistration festgelegt werden. Dies ist nützlich, wenn Sie einige Integritätsprüfungen in einem anderen Rhythmus als dem in HealthCheckPublisherOptions festgelegten Zeitraum durchführen möchten.
Mit dem folgenden Code wird Delay
und Period
für SampleHealthCheck1
festgelegt:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks()
.Add(new HealthCheckRegistration(
name: "SampleHealthCheck1",
instance: new SampleHealthCheck(),
failureStatus: null,
tags: null,
timeout: default)
{
Delay = TimeSpan.FromSeconds(40),
Period = TimeSpan.FromSeconds(30)
});
var app = builder.Build();
app.MapHealthChecks("/healthz");
app.Run();
Abhängigkeitsinjektion und Integritätsprüfungen
Es ist möglich, eine Instanz eines bestimmten Type
innerhalb einer Integritätsprüfungsklasse über eine Abhängigkeitsinjektion zu verwenden. Die Abhängigkeitsinjektion kann hilfreich sein, um Optionen oder eine globale Konfiguration in eine Integritätsprüfung einzufügen. Die Verwendung der Abhängigkeitsinjektion ist kein gängiges Szenario zum Konfigurieren von Integritätsprüfungen. In der Regel ist jede Integritätsprüfung spezifisch für den tatsächlichen Test und wird mithilfe von IHealthChecksBuilder
-Erweiterungsmethoden konfiguriert.
Das folgende Beispiel zeigt ein Beispiel für eine Integritätsprüfung, die ein Konfigurationsobjekt über eine Abhängigkeitsinjektion abruft:
public class SampleHealthCheckWithDI : IHealthCheck
{
private readonly SampleHealthCheckWithDiConfig _config;
public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
=> _config = config;
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// use _config ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
SampleHealthCheckWithDiConfig
und die Integritätsprüfung müssen dem Dienstcontainer hinzugefügt werden:
builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheckWithDI>(
"With Dependency Injection",
tags: new[] { "inject" });
UseHealthChecks im Vergleich zu MapHealthChecks
Es gibt zwei Möglichkeiten, Integritätsprüfungen für Aufrufer zugänglich zu machen:
- UseHealthChecks registriert Middleware für die Verarbeitung von Integritätsprüfungsanforderungen in der Middlewarepipeline.
- MapHealthChecks registriert einen Integritätsprüfungsendpunkt. Der Endpunkt wird zusammen mit anderen Endpunkten in der App abgeglichen und ausgeführt.
Der Vorteil der Verwendung von MapHealthChecks
gegenüber UseHealthChecks
ist die Möglichkeit, endpunktfähige Middleware wie Autorisierung zu verwenden und eine präzisere Kontrolle über die Abgleichsrichtlinie zu haben. Der Hauptvorteil der Verwendung von UseHealthChecks
gegenüber MapHealthChecks
besteht darin, genau zu steuern, wo Integritätsprüfungen in der Middlewarepipeline ausgeführt werden.
- Beendet die Pipeline, wenn eine Anforderung mit dem Integritätsprüfungsendpunkt übereinstimmt. Kurzschlüsse sind häufig wünschenswert, da dadurch unnötige Arbeit vermieden wird, z. B. Protokollierung und andere Middleware.
- Wird in erster Linie zum Konfigurieren der Integritätsprüfungsmiddleware in der Pipeline verwendet.
- Kann einen beliebigen Pfad an einem Port mit einem
null
-Wert oder einem leerenPathString
-Wert abgleichen. Ermöglicht das Durchführen einer Integritätsprüfung für jede Anforderung, die an den angegebenen Port gestellt wird. - Quellcode
MapHealthChecks ermöglicht:
- Beendet die Pipeline, wenn eine Anforderung mit dem Integritätsprüfungsendpunkt übereinstimmt, indem ShortCircuit aufgerufen wird. Beispiel:
app.MapHealthChecks("/healthz").ShortCircuit();
. Weitere Informationen finden Sie unter Kurzschluss der Middleware nach dem Routing. - Zuordnen bestimmter Routen oder Endpunkte für Integritätsprüfungen.
- Anpassen der URL oder des Pfads, unter der bzw. dem auf den Integritätsprüfungsendpunkt zugegriffen werden kann.
- Zuordnen mehrerer Integritätsprüfungsendpunkte mit unterschiedlichen Routen oder Konfigurationen. Unterstützung mehrerer Endpunkte:
- Aktiviert separate Endpunkte für verschiedene Arten von Integritätsprüfungen oder -komponenten.
- Wird verwendet, um zwischen verschiedenen Aspekten der App-Integrität zu unterscheiden oder bestimmte Konfigurationen auf Teilmengen von Integritätsprüfungen anzuwenden.
- Quellcode
Zusätzliche Ressourcen
Hinweis
Dieser Artikel wurde teilweise mit Hilfe künstlicher Intelligenz erstellt. Vor der Veröffentlichung hat ein Autor den Inhalt geprüft und nach Bedarf überarbeitet. Weitere Informationen finden Sie unter Unsere Prinzipien für die Verwendung von KI-generierten Inhalten in Microsoft Learn.
ASP.NET Core bietet Middleware für Integritätsprüfungen und Bibliotheken für die Berichterstellung für Komponenten der App-Infrastruktur.
Integritätsprüfungen werden von einer App als HTTP-Endpunkte verfügbar gemacht. Endpunkte für die Integritätsprüfung können für verschiedene Echtzeitüberwachungsszenarien konfiguriert werden:
- Integritätstests können von Containerorchestratoren und Lastenausgleichsmodulen verwendet werden, um den Status einer App zu überprüfen. Ein Containerorchestrator kann z.B. auf eine fehlerhafte Integritätsprüfung reagieren, indem die Ausführung einer Bereitstellung angehalten oder ein Container neu gestartet wird. Ein Lastenausgleichsmodul kann auf eine fehlerhafte App reagieren, indem Datenverkehr von der fehlerhaften zu einer fehlerfreien Instanz umgeleitet wird.
- Die Nutzung von Arbeitsspeicher, Datenträgern und anderen physischen Serverressourcen kann auf einen fehlerfreien Status überwacht werden.
- Integritätsprüfungen können die Abhängigkeiten einer App testen, wie z.B. Datenbanken und externe Dienstendpunkte, um Verfügbarkeit und normale Funktionsweise zu bestätigen.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Die Beispiel-App enthält Beispiele der in diesem Artikel beschriebenen Szenarien. Um die Beispiel-App für ein bestimmtes Szenario auszuführen, verwenden Sie den Befehl dotnet run aus dem Ordner des Projekts in einer Befehlsshell. Informationen zur Verwendung der Beispiel-App finden Sie in der zugehörigen Datei README.md
und den Szenariobeschreibungen in diesem Artikel.
Voraussetzungen
Integritätsprüfungen werden in der Regel mit einem externen Überwachungsdienst oder Containerorchestrator verwendet, um den Status einer App zu überprüfen. Bevor Sie Integritätsprüfungen zu einer App hinzufügen, entscheiden Sie, welches Überwachungssystem verwendet werden soll. Das Überwachungssystem bestimmt, welche Arten von Integritätsprüfungen erstellt und wie die jeweiligen Endpunkte konfiguriert werden müssen.
Für ASP.NET Core-Apps wird implizit auf das Paket Microsoft.AspNetCore.Diagnostics.HealthChecks
verwiesen. Fügen Sie einen Verweis auf das Paket Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
hinzu, um Integritätsprüfungen mit Entity Framework Core durchzuführen.
Die Beispiel-App stellt Startcode bereit, um die Integritätsprüfungen für verschiedene Szenarien zu veranschaulichen. Das Szenario Datenbanktest überprüft die Integrität einer Datenbankverbindung mithilfe von AspNetCore.Diagnostics.HealthChecks
. Im Szenario DbContext-Test wird eine Datenbank mithilfe eines EF Core-DbContext
überprüft. Für ein Erkunden der Datenbankszenarios gilt für die Beispiel-App:
- Sie erstellt eine Datenbank und stellt deren Verbindungszeichenfolge in der
appsettings.json
-Datei bereit. - Sie hat die folgenden Paketverweise in ihrer Projektdatei:
Hinweis
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Ein anderes Szenario für Integritätsprüfungen zeigt, wie Sie Integritätsprüfungen auf einen Verwaltungsport filtern können. Für die Beispiel-App müssen Sie eine Properties/launchSettings.json
-Datei erstellen, die die Verwaltungs-URL und den Verwaltungsport enthält. Weitere Informationen finden Sie im Abschnitt Filtern nach Port.
Grundlegender Integritätstest
In vielen Apps genügt zur Ermittlung des App-Status eine grundlegende Integritätstestkonfiguration, die die Verfügbarkeit der App für die Verarbeitung von Anforderungen (Lebendigkeit) meldet.
Die grundlegende Konfiguration registriert Integritätsprüfungsdienste und ruft die Middleware für Integritätsprüfungen auf, damit diese an einem URL-Endpunkt mit dem Integritätsstatus antwortet. Standardmäßig werden keine spezifischen Integritätsprüfungen registriert, um eine bestimmte Abhängigkeit oder ein bestimmtes Subsystem zu testen. Die App wird als fehlerfrei angesehen, wenn sie an der URL des Integritätsendpunkts antworten kann. Der standardmäßig verwendete Antwortwriter schreibt den Status (HealthStatus) als Nur-Text-Antwort zurück an den Client und gibt dabei den Status HealthStatus.Healthy, HealthStatus.Degraded oder HealthStatus.Unhealthy an.
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Erstellen Sie einen Integritätsprüfungs-Endpunkt durch Aufrufen von MapHealthChecks
in Startup.Configure
.
In der Beispiel-App wird der Integritätsprüfungs-Endpunkt in /health
(BasicStartup.cs
) erstellt:
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
Um das Szenario für die grundlegende Konfiguration mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario basic
Docker-Beispiel
Docker bietet eine integrierte HEALTHCHECK
-Direktive, mit der Sie den Status einer App überprüfen können, die die grundlegende Konfiguration für Integritätsprüfungen verwendet:
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
Erstellen von Integritätsprüfungen
Integritätsprüfungen werden durch Implementieren der IHealthCheck-Schnittstelle erstellt. Die CheckHealthAsync-Methode gibt ein HealthCheckResult zurück, das die Integrität als Healthy
, Degraded
oder Unhealthy
angibt. Das Ergebnis wird als Klartextantwort mit einem konfigurierbaren Statuscode geschrieben (diese Konfiguration wird im Abschnitt Optionen für die Integritätsprüfung beschrieben). HealthCheckResult kann auch optionale Schlüssel-Wert-Paare zurückgeben.
Die folgende ExampleHealthCheck
-Klasse veranschaulicht das Layout einer Integritätsprüfung. Die Integritätsprüfungslogik wird in der CheckHealthAsync
-Methode platziert. Im folgenden Beispiel wird eine Dummyvariable healthCheckResultHealthy
auf true
festgelegt. Wenn der Wert von healthCheckResultHealthy
auf false
festgelegt ist, wird der HealthCheckRegistration.FailureStatus-Status zurückgegeben.
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(context.Registration.FailureStatus,
"An unhealthy result."));
}
}
Wenn CheckHealthAsync während der Überprüfung eine Ausnahme auslöst, wird eine neue HealthReportEntry-Struktur zurückgegeben, bei der die Eigenschaft HealthReportEntry.Status, die von AddCheck definiert wird, auf FailureStatus festgelegt ist (vgl. Abschnitt Registrieren von Integritätsprüfungsdiensten) und die die innere Ausnahme enthält, die den Überprüfungsfehler ursprünglich verursacht hat. Description ist auf die Meldung der Ausnahme festgelegt.
Registrieren von Integritätsprüfungsdiensten
Der ExampleHealthCheck
-Typ wird mit AddCheck in Startup.ConfigureServices
den Integritätsprüfungsdiensten hinzugefügt:
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
Die in der folgenden Abbildung gezeigte AddCheck-Überladung legt den Fehlerstatus (HealthStatus) fest, der angegeben werden soll, wenn die Integritätsprüfung einen Fehler meldet. Wenn der Fehlerstatus auf null
(Standardwert) festgelegt ist, wird HealthStatus.Unhealthy gemeldet. Diese Überladung ist ein nützliches Szenario für Bibliotheksersteller: Bei einem Integritätsprüfungsfehler wird der durch die Bibliothek angegebene Fehlerstatus von der App erzwungen, wenn die Implementierung der Integritätsprüfung die Einstellung berücksichtigt.
Tags können zum Filtern von Integritätsprüfungen verwendet werden (dies wird im Abschnitt Filtern von Integritätsprüfungen genauer beschrieben).
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck kann auch eine Lambdafunktion ausführen. Im folgenden Beispiel wird der Name der Integritätsprüfung als Example
angegeben, und die Prüfung gibt immer einen fehlerfreien Status zurück:
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
Rufen Sie AddTypeActivatedCheck auf, um Argumente an die Implementierung einer Integritätsprüfung zu übergeben. Im folgenden Beispiel akzeptiert TestHealthCheckWithArgs
eine ganze Zahl und eine Zeichenfolge, wenn CheckHealthAsync aufgerufen wird:
private class TestHealthCheckWithArgs : IHealthCheck
{
public TestHealthCheckWithArgs(int i, string s)
{
I = i;
S = s;
}
public int I { get; set; }
public string S { get; set; }
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
CancellationToken cancellationToken = default)
{
...
}
}
TestHealthCheckWithArgs
wird durch Aufrufen von AddTypeActivatedCheck
mit der Übergabe der ganzen Zahl und der Zeichenfolge an die Implementierung registriert:
services.AddHealthChecks()
.AddTypeActivatedCheck<TestHealthCheckWithArgs>(
"test",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" },
args: new object[] { 5, "string" });
Verwenden von Integritätsprüfungsrouting
Rufen Sie in Startup.Configure
auf der Endpunkterstellung mit der Endpunkt-URL oder dem relativen Pfad MapHealthChecks
auf:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Anfordern des Hosts
Rufen Sie RequireHost
auf, um einen oder mehrere zugelassene Hosts für den Integritätsprüfungs-Endpunkt anzugeben. Hosts sollten Unicode anstelle von Punycode verwenden und können einen Port enthalten. Wenn keine Sammlung bereitgestellt wird, wird jeder Host akzeptiert.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});
Weitere Informationen finden Sie im Abschnitt Filtern nach Port.
Anfordern der Autorisierung
Rufen Sie RequireAuthorization
auf, um die Autorisierungsmiddleware auf dem Integritätsprüfungs-Anforderungsendpunkt auszuführen. Eine RequireAuthorization
-Überladung akzeptiert eine oder mehrere Autorisierungsrichtlinien. Wenn keine Richtlinie bereitgestellt wird, wird die standardmäßige Autorisierungsrichtlinie verwendet.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireAuthorization();
});
Aktivieren ursprungsübergreifender Anforderungen (CORS)
Obwohl das manuelle Ausführen von Integritätsprüfungen über einen Browser kein gängiges Szenario ist, kann CORS-Middleware durch Aufrufen von RequireCors
für Integritätsprüfungsendpunkte aktiviert werden. Eine RequireCors
-Überladung akzeptiert einen CORS-Richtliniengenerator-Delegaten (CorsPolicyBuilder
) oder einen Richtliniennamen. Wenn keine Richtlinie bereitgestellt wird, wird die standardmäßige CORS-Richtlinie verwendet. Weitere Informationen finden Sie unter Aktivieren ursprungsübergreifender Anforderungen (Cross-Origin Requests, CORS) in ASP.NET Core.
Optionen für die Integritätsprüfung
HealthCheckOptions ermöglichen die Anpassung des Verhaltens von Integritätsprüfungen:
- Filtern von Integritätsprüfungen
- Anpassen des HTTP-Statuscodes
- Unterdrücken von Cacheheadern
- Anpassen der Ausgabe
Filtern von Integritätsprüfungen
Standardmäßig führt die Middleware für Integritätsprüfungen alle registrierten Integritätsprüfungen aus. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die einen booleschen Wert an die Option Predicate zurückgibt. Im folgenden Beispiel wird die Bar
-Integritätsprüfung anhand ihres Tags (bar_tag
) in der Bedingungsanweisung der Funktion herausgefiltert. Dabei wird true
nur zurückgegeben, wenn die Tags-Eigenschaft der Integritätsprüfung mit foo_tag
oder baz_tag
übereinstimmt:
In Startup.ConfigureServices
:
services.AddHealthChecks()
.AddCheck("Foo", () =>
HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
.AddCheck("Bar", () =>
HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
.AddCheck("Baz", () =>
HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });
In Startup.Configure
filtert Predicate
die „Bar“-Integritätsprüfung heraus. Nur Foo und Baz werden ausgeführt:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
});
Anpassen des HTTP-Statuscodes
Verwenden Sie ResultStatusCodes, um die Zuordnung des Integritätsstatus zu HTTP-Statuscodes anzupassen. Die folgenden StatusCodes-Zuweisungen stellen die von der Middleware verwendeten Standardwerte dar. Ändern Sie die Statuscodewerte so, dass sie Ihren Anforderungen entsprechen.
In Startup.Configure
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
});
Unterdrücken von Cacheheadern
AllowCachingResponses steuert, ob die Middleware für Integritätsprüfungen einer Testantwort HTTP-Header hinzufügt, um das Zwischenspeichern von Antworten zu verhindern. Wenn der Wert false
(Standard) lautet, legt die Middleware die Header Cache-Control
, Expires
und Pragma
fest oder überschreibt sie, um eine Zwischenspeicherung der Antworten zu verhindern. Wenn der Wert true
lautet, ändert die Middleware die Cacheheader der Antwort nicht.
In Startup.Configure
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = true
});
});
Anpassen der Ausgabe
Legen Sie in Startup.Configure
die Option HealthCheckOptions.ResponseWriter auf einen Delegaten für das Schreiben der Antwort fest:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
});
Der Standarddelegat schreibt eine minimale Klartextantwort mit dem Zeichenfolgenwert HealthReport.Status
. Der folgende benutzerdefinierte Delegat gibt eine benutzerdefinierte JSON-Antwort aus.
Das erste Beispiel aus der Beispiel-App veranschaulicht die Verwendung von System.Text.Json:
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions
{
Indented = true
};
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartObject();
writer.WriteString("status", result.Status.ToString());
writer.WriteStartObject("results");
foreach (var entry in result.Entries)
{
writer.WriteStartObject(entry.Key);
writer.WriteString("status", entry.Value.Status.ToString());
writer.WriteString("description", entry.Value.Description);
writer.WriteStartObject("data");
foreach (var item in entry.Value.Data)
{
writer.WritePropertyName(item.Key);
JsonSerializer.Serialize(
writer, item.Value, item.Value?.GetType() ??
typeof(object));
}
writer.WriteEndObject();
writer.WriteEndObject();
}
writer.WriteEndObject();
writer.WriteEndObject();
}
var json = Encoding.UTF8.GetString(stream.ToArray());
return context.Response.WriteAsync(json);
}
}
Im zweiten Beispiel wird veranschaulicht, wie Newtonsoft.Json
verwendet wird:
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json";
var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
return context.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
Kommentieren Sie in der Beispiel-App die Präprozessoranweisung SYSTEM_TEXT_JSON
in CustomWriterStartup.cs
aus, um die Newtonsoft.Json
-Version von WriteResponse
zu aktivieren.
Die Integritätsprüfungs-API bietet keine integrierte Unterstützung für komplexe JSON-Rückgabeformate, da das Format für Ihre Überwachungssystemauswahl spezifisch ist. Passen Sie die Antwort in den vorangehenden Beispielen nach Bedarf an. Weitere Informationen zur JSON-Serialisierung mit System.Text.Json
finden Sie unter Serialisieren und Deserialisieren von JSON in .NET.
Datenbanktest
Eine Integritätsprüfung kann eine Datenbankabfrage angeben, die als boolescher Test ausgeführt wird, um zu ermitteln, ob die Datenbank normal reagiert.
Die Beispiel-App verwendet AspNetCore.Diagnostics.HealthChecks
, eine Bibliothek für Integritätsprüfungen für ASP.NET Core-Apps, um eine Integritätsprüfung für eine SQL Server-Datenbank-Instanz auszuführen. AspNetCore.Diagnostics.HealthChecks
führt eine SELECT 1
-Abfrage in der Datenbank aus, um zu bestätigen, dass die Verbindung mit der Datenbank fehlerfrei ist.
Warnung
Wenn Sie die Datenbankverbindung mithilfe einer Abfrage überprüfen, wählen Sie eine Abfrage aus, die eine schnelle Antwort zurückgibt. Bei einer Abfrage besteht immer das Risiko, dass die Datenbank überladen und ihre Leistung beeinträchtigt wird. In den meisten Fällen ist es nicht notwendig, eine Testabfrage auszuführen. Es genügt zumeist, einfach erfolgreich eine Verbindung mit der Datenbank herzustellen. Wenn Sie eine Abfrage ausführen müssen, wählen Sie eine einfache SELECT-Abfrage aus, wie z.B. SELECT 1
.
Fügen Sie einen Paketverweis auf AspNetCore.HealthChecks.SqlServer
hinzu.
Geben Sie in der appsettings.json
-Datei der App eine gültige Zeichenfolge für die Datenbankverbindung an. Die App verwendet eine SQL Server-Datenbank namens HealthCheckSample
:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"IncludeScopes": "true"
}
},
"AllowedHosts": "*"
}
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Die Beispiel-App ruft die AddSqlServer
-Methode mit der Verbindungszeichenfolge der Datenbank (DbHealthStartup.cs
) auf:
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Um das Szenario für den Datenbanktest mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario db
Hinweis
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Entity Framework Core-DbContext-Test
Die DbContext
-Überprüfung bestätigt, dass die App mit der Datenbank kommunizieren kann, die für einen EF Core-DbContext
konfiguriert wurde. Die DbContext
Überprüfung wird in Apps unterstützt, für die gilt:
- In ihnen wird Entity Framework Core (EF Core) verwendet.
- Fügen Sie einen Paketverweis auf
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
hinzu.
AddDbContextCheck<TContext>
registriert eine Integritätsprüfung für einen DbContext
. Der DbContext
wird als der TContext
für die Methode bereitgestellt. Eine Überladung ist verfügbar, um den Fehlerstatus, Tags sowie eine benutzerdefinierte Testabfrage zu konfigurieren.
Standardmäßig:
- Der
DbContextHealthCheck
ruft dieCanConnectAsync
-Methode von EF Core auf. Sie können festlegen, welcher Vorgang ausgeführt wird, wenn die Integrität mitAddDbContextCheck
-Methodenüberladungen überprüft wird. - Der Name der Integritätsprüfung ist der Name des
TContext
-Typs.
In der Beispiel-App wird AppDbContext
für AddDbContextCheck
bereitgestellt und als Dienst in Startup.ConfigureServices
(DbContextHealthStartup.cs
) registriert:
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Stellen Sie sicher, dass die mit der Verbindungszeichenfolge angegebene Datenbank in der SQL Server-Instanz nicht vorhanden ist, um das DbContext
-Testszenario mithilfe der Beispiel-App ausführen zu können. Falls die Datenbank vorhanden ist, löschen Sie sie.
Führen Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell aus:
dotnet run --scenario dbcontext
Wenn die App ausgeführt wird, überprüfen Sie den Integritätsstatus, indem Sie in einem Browser eine Anforderung an den /health
-Endpunkt senden. Datenbank und AppDbContext
sind nicht vorhanden, also sendet die App die folgende Antwort:
Unhealthy
Fordern Sie die Beispiel-App auf, die Datenbank zu erstellen. Senden Sie eine /createdatabase
-Anforderung. Die App sendet die folgende Antwort:
Creating the database...
Done!
Navigate to /health to see the health status.
Senden Sie eine Anforderung an den /health
-Endpunkt. Datenbank und Kontext sind vorhanden, also sendet die App die folgende Antwort:
Healthy
Fordern Sie die Beispiel-App auf, die Datenbank zu löschen. Senden Sie eine /deletedatabase
-Anforderung. Die App sendet die folgende Antwort:
Deleting the database...
Done!
Navigate to /health to see the health status.
Senden Sie eine Anforderung an den /health
-Endpunkt. Die App meldet einen fehlerhaften Status:
Unhealthy
Separate Tests für Bereitschaft und Lebendigkeit
In einigen Hostingszenarien wird ein Integritätsprüfungspaar verwendet, mit dem zwischen zwei App-Status unterschieden wird:
- Bereitschaft gibt an, ob die App ordnungsgemäß ausgeführt wird, aber nicht für den Empfang von Anforderungen bereit ist.
- Livetest gibt an, ob eine App abgestürzt ist und neu gestartet werden muss.
Betrachten Sie das folgende Beispiel: Eine App muss eine große Konfigurationsdatei herunterladen, bevor sie für die Verarbeitung von Anforderungen bereit ist. Wir möchten nicht, dass die App neu gestartet wird, wenn der erste Download fehlschlägt, da die App mehrmals versuchen kann, die Datei herunterzuladen. Wir verwenden einen Livetest, um den Livezustand des Prozesses zu beschreiben. Weitere Überprüfungen erfolgen nicht. Außerdem soll verhindert werden, dass Anforderungen an die App gesendet werden, bevor die Konfigurationsdatei erfolgreich heruntergeladen wurde. Wir verwenden einen Bereitschaftstest, um den Status "nicht bereit" anzugeben, bis der Download erfolgreich durchgeführt wurde und die App für den Empfang von Anforderungen bereit ist.
Die Beispiel-App enthält eine Integritätsprüfung, um den Abschluss eines Starttasks mit langer Ausführungsdauer in einem gehosteten Dienst zu melden. StartupHostedServiceHealthCheck
macht die Eigenschaft StartupTaskCompleted
verfügbar, die der gehostete Dienst auf true
festlegen kann, wenn der Task mit langer Ausführungsdauer abgeschlossen ist (StartupHostedServiceHealthCheck.cs
):
public class StartupHostedServiceHealthCheck : IHealthCheck
{
private volatile bool _startupTaskCompleted = false;
public string Name => "slow_dependency_check";
public bool StartupTaskCompleted
{
get => _startupTaskCompleted;
set => _startupTaskCompleted = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
if (StartupTaskCompleted)
{
return Task.FromResult(
HealthCheckResult.Healthy("The startup task is finished."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("The startup task is still running."));
}
}
Der Hintergrundtask mit langer Ausführungsdauer wird von einem gehosteten Dienst (Services/StartupHostedService
) gestartet. Nach Abschluss des Tasks wird StartupHostedServiceHealthCheck.StartupTaskCompleted
auf true
festgelegt:
public class StartupHostedService : IHostedService, IDisposable
{
private readonly int _delaySeconds = 15;
private readonly ILogger _logger;
private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;
public StartupHostedService(ILogger<StartupHostedService> logger,
StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
{
_logger = logger;
_startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is starting.");
// Simulate the effect of a long-running startup task.
Task.Run(async () =>
{
await Task.Delay(_delaySeconds * 1000);
_startupHostedServiceHealthCheck.StartupTaskCompleted = true;
_logger.LogInformation("Startup Background Service has started.");
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is stopping.");
return Task.CompletedTask;
}
public void Dispose()
{
}
}
Die Integritätsprüfung wird mit AddCheck zusammen mit dem gehosteten Dienst in Startup.ConfigureServices
registriert. Da der gehostete Dienst die Eigenschaft in der Integritätsprüfung festlegen muss, wird die Integritätsprüfung ebenfalls im Dienstcontainer (LivenessProbeStartup.cs
) registriert:
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();
services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt. In der Beispiel-App wird der Integritätsprüfungs-Endpunkt erstellt unter:
/health/ready
für die Bereitschaftsprüfung. Die Bereitschaftsprüfung filtert auf Integritätsprüfungen mit demready
-Tag./health/live
für die Lebendigkeitsprüfung. Die Lebendigkeitsprüfung filtertStartupHostedServiceHealthCheck
durch Rückgabe vonfalse
inHealthCheckOptions.Predicate
heraus (weitere Informationen unter Filtern von Integritätsprüfungen).
Im folgenden Beispielcode gilt Folgendes:
- Die Bereitschaftsprüfung verwendet alle registrierten Überprüfungen mit dem Tag „Bereit“.
Predicate
schließt alle Überprüfungen aus und gibt 200-OK zurück.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Um das Szenario für die Konfiguration von Bereitschafts-/Lebendigkeitsprüfungen mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario liveness
Besuchen Sie /health/ready
mehrmals in einem Browser, bis 15 Sekunden verstrichen sind. Die Integritätsprüfung meldet während der ersten 15 Sekunden Unhealthy
. Nach 15 Sekunden meldet der Endpunkt Healthy
, was darauf hindeutet, dass die Ausführung des Tasks mit langer Ausführungsdauer durch den gehosteten Dienst abgeschlossen wurde.
In diesem Beispiel wird auch ein Integritätsprüfungsherausgeber erstellt (IHealthCheckPublisher-Implementierung), der die erste Bereitschaftsprüfung mit einer Verzögerung von zwei Sekunden ausführt. Weitere Informationen finden Sie im Abschnitt Herausgeber der Integritätsprüfung.
Kubernetes-Beispiel
Die Verwendung von Bereitschafts- und Lebendigkeitstests ist in Umgebungen wie Kubernetes sehr nützlich. In Kubernetes muss eine App möglicherweise zeitaufwendige Startaufgaben ausführen, bevor sie Anforderungen wie z. B. das Testen der Verfügbarkeit der zugrunde liegenden Datenbank erfüllt. Durch Verwendung separater Überprüfungen kann der Orchestrator unterscheiden, ob eine App funktioniert, aber noch nicht bereit ist, oder ob die App nicht gestartet wurde. Weitere Informationen zu Bereitschafts- und Lebendigkeitstests in Kubernetes finden Sie in der Kubernetes-Dokumentation unter Configure Liveness and Readiness Probes (Konfigurieren von Lebendigkeits- und Bereitschaftstests).
Das folgende Beispiel veranschaulicht die Konfiguration eines Bereitschaftstests in Kubernetes:
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /health/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
Metrikbasierter Test mit einem benutzerdefinierten Antwortwriter
Die Beispiel-App veranschaulicht eine Arbeitsspeicher-Integritätsprüfung mit einem benutzerdefinierten Antwortwriter.
MemoryHealthCheck
meldet einen beeinträchtigten Status, wenn die App mehr Arbeitsspeicher verwendet, als für den Schwellenwert festgelegt wurde (1 GB in der Beispiel-App). Das HealthCheckResult enthält Garbage Collector-Informationen (GC) für die App (MemoryHealthCheck.cs
):
public class MemoryHealthCheck : IHealthCheck
{
private readonly IOptionsMonitor<MemoryCheckOptions> _options;
public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
{
_options = options;
}
public string Name => "memory_check";
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var options = _options.Get(context.Registration.Name);
// Include GC information in the reported diagnostics.
var allocated = GC.GetTotalMemory(forceFullCollection: false);
var data = new Dictionary<string, object>()
{
{ "AllocatedBytes", allocated },
{ "Gen0Collections", GC.CollectionCount(0) },
{ "Gen1Collections", GC.CollectionCount(1) },
{ "Gen2Collections", GC.CollectionCount(2) },
};
var status = (allocated < options.Threshold) ?
HealthStatus.Healthy : context.Registration.FailureStatus;
return Task.FromResult(new HealthCheckResult(
status,
description: "Reports degraded status if allocated bytes " +
$">= {options.Threshold} bytes.",
exception: null,
data: data));
}
}
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Die Integritätsprüfung wird nicht durch Übergabe an AddCheck aktiviert, stattdessen wird MemoryHealthCheck
als Dienst registriert. Alle bei IHealthCheck registrierten Dienste stehen für die Dienste und Middleware für Integritätsprüfungen zur Verfügung. Es wird empfohlen, Integritätsprüfungsdienste als Singleton-Dienste zu registrieren.
In CustomWriterStartup.cs
der Beispiel-App:
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt. Ein WriteResponse
-Delegat wird in der ResponseWriter-Eigenschaft angegeben, um eine benutzerdefinierte JSON-Antwort auszugeben, wenn die Integritätsprüfung ausgeführt wird:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
}
Der WriteResponse
-Delegat formatiert das CompositeHealthCheckResult
als JSON-Objekt und führt zu folgender JSON-Ausgabe für die Integritätsprüfungsantwort. Weitere Informationen finden Sie im Abschnitt Anpassen der Ausgabe.
Um den metrikbasierten Test mit benutzerdefinierter Ausgabe des Antwortwriters mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario writer
Hinweis
AspNetCore.Diagnostics.HealthChecks
enthält Szenarios für metrikbasierte Integritätsprüfungen, einschließlich Prüfungen des Datenträgerspeichers und Lebendigkeitsprüfungen mit Maximalwert.
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Filtern nach Port
Rufen Sie RequireHost
auf MapHealthChecks
mit einem URL-Muster auf, das einen Port angibt, um die an diesen Port gerichteten Integritätsprüfungsanforderungen einzuschränken. Dieser Ansatz wird normalerweise in einer Containerumgebung verfolgt, um einen Port für Überwachungsdienste verfügbar zu machen.
Die Beispiel-App konfiguriert den Port mithilfe des Umgebungsvariablen-Konfigurationsanbieters. Der Port wird in der Datei launchSettings.json
festgelegt und über eine Umgebungsvariable an den Konfigurationsanbieter übergeben. Sie müssen den Server auch so konfigurieren, dass er am Verwaltungsport auf Anforderungen lauscht.
Um die Beispiel-App zum Veranschaulichen der Konfiguration des Verwaltungsports zu verwenden, erstellen Sie die Datei launchSettings.json
in einem Properties
-Ordner.
Die folgende Properties/launchSettings.json
-Datei in der Beispiel-App ist in den Projektdateien der Beispiel-App nicht vorhanden und muss manuell erstellt werden:
{
"profiles": {
"SampleApp": {
"commandName": "Project",
"commandLineArgs": "",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
"ASPNETCORE_MANAGEMENTPORT": "5001"
},
"applicationUrl": "http://localhost:5000/"
}
}
}
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Erstellen Sie einen Integritätsprüfungs-Endpunkt durch Aufrufen von MapHealthChecks
in Startup.Configure
.
In der Beispiel-App gibt ein Aufruf von RequireHost
auf dem Endpunkt in Startup.Configure
den Verwaltungsport aus der Konfiguration an:
endpoints.MapHealthChecks("/health")
.RequireHost($"*:{Configuration["ManagementPort"]}");
Endpunkte werden in der Beispiel-App in Startup.Configure
erstellt. Im folgenden Beispielcode gilt Folgendes:
- Die Bereitschaftsprüfung verwendet alle registrierten Überprüfungen mit dem Tag „Bereit“.
Predicate
schließt alle Überprüfungen aus und gibt 200-OK zurück.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Hinweis
Sie können vermeiden, die Datei launchSettings.json
in der Beispiel-App erstellen zu müssen, indem Sie den Verwaltungsport explizit im Code festlegen. Fügen Sie in Program.cs
an der Stelle, an der HostBuilder erstellt wird, einen Aufruf von ListenAnyIP hinzu, und geben Sie den Endpunkt des Verwaltungsports der App an. Geben Sie in Configure
von ManagementPortStartup.cs
den Verwaltungsport mit RequireHost
an:
Program.cs
:
return new HostBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5001);
})
.UseStartup(startupType);
})
.Build();
ManagementPortStartup.cs
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});
Um das Szenario für die Konfiguration des Verwaltungsports mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario port
Verteilen einer Integritätsprüfungsbibliothek
So verteilen Sie eine Integritätsprüfung als Bibliothek:
Schreiben Sie eine Integritätsprüfung, die die IHealthCheck-Schnittstelle als eigenständige Klasse implementiert. Die Klasse kann Abhängigkeitsinjektion (Dependency Injection, DI), Typaktivierung und benannte Optionen verwenden, um auf Konfigurationsdaten zuzugreifen.
In der Integritätsprüfungslogik von
CheckHealthAsync
gilt Folgendes:data1
unddata2
werden in der Methode verwendet, um die Integritätsprüfungslogik des Tests auszuführen.AccessViolationException
wird verarbeitet.
Wenn eine AccessViolationException auftritt, wird der FailureStatus mit dem HealthCheckResult zurückgegeben, damit Benutzer den Integritätsprüfungs-Fehlerstatus konfigurieren können.
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace SampleApp { public class ExampleHealthCheck : IHealthCheck { private readonly string _data1; private readonly int? _data2; public ExampleHealthCheck(string data1, int? data2) { _data1 = data1 ?? throw new ArgumentNullException(nameof(data1)); _data2 = data2 ?? throw new ArgumentNullException(nameof(data2)); } public async Task<HealthCheckResult> CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken) { try { return HealthCheckResult.Healthy(); } catch (AccessViolationException ex) { return new HealthCheckResult( context.Registration.FailureStatus, description: "An access violation occurred during the check.", exception: ex, data: null); } } } }
Schreiben Sie eine Erweiterungsmethode mit Parametern, die von der nutzenden App in ihrer
Startup.Configure
-Methode aufgerufen werden. Nehmen Sie im folgenden Beispiel die folgende Signatur für die Integritätsprüfungsmethode an:ExampleHealthCheck(string, string, int )
Die oben stehende Signatur gibt an, dass
ExampleHealthCheck
weitere Daten benötigt, um die Testlogik für die Integritätsprüfung zu verarbeiten. Die Daten werden für den Delegaten bereitgestellt, der zum Erstellen der Integritätsprüfungsinstanz verwendet wird, wenn die Integritätsprüfung bei einer Erweiterungsmethode registriert wird. Im folgenden Beispiel gibt der Aufrufer optional Folgendes an:- Name der Integritätsprüfung (
name
). Wenn der Wertnull
ist, wirdexample_health_check
verwendet. - string-Datenpunkt für die Integritätsprüfung (
data1
). - integer-Datenpunkt für die Integritätsprüfung (
data2
). Wenn der Wertnull
ist, wird1
verwendet. - Fehlerstatus (HealthStatus). Der Standardwert ist
null
. Wenn der Wertnull
ist, wird HealthStatus.Unhealthy für einen Fehlerstatus gemeldet. - Tags (
IEnumerable<string>
).
using System.Collections.Generic; using Microsoft.Extensions.Diagnostics.HealthChecks; public static class ExampleHealthCheckBuilderExtensions { const string DefaultName = "example_health_check"; public static IHealthChecksBuilder AddExampleHealthCheck( this IHealthChecksBuilder builder, string name = default, string data1, int data2 = 1, HealthStatus? failureStatus = default, IEnumerable<string> tags = default) { return builder.Add(new HealthCheckRegistration( name ?? DefaultName, sp => new ExampleHealthCheck(data1, data2), failureStatus, tags)); } }
- Name der Integritätsprüfung (
Herausgeber der Integritätsprüfung
Wenn dem Dienstcontainer ein IHealthCheckPublisher hinzugefügt wird, führt das Integritätsprüfungssystem Ihre Integritätsprüfungen regelmäßig aus und ruft PublishAsync
mit dem Ergebnis auf. Dies ist nützlich in einem Szenario mit pushbasiertem Integritätsüberwachungssystem, in dem jeder Prozess das Überwachungssystem regelmäßig aufrufen muss, um die Integrität zu bestimmen.
Die IHealthCheckPublisher-Schnittstelle weist eine einzige Methode auf:
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions ermöglichen Ihnen, Folgendes festzulegen:
- Delay: Hierbei handelt es sich um die angewendete anfängliche Verzögerung zwischen dem Start der App und der Ausführung von IHealthCheckPublisher-Instanzen. Die Verzögerung wird einmal beim Start angewendet und gilt nicht für die nachfolgenden Iterationen. Der Standardwert beträgt fünf Sekunden.
- Period: Hierbei handelt es sich um die Dauer der Ausführung von IHealthCheckPublisher. Der Standardwert ist 30 Sekunden.
- Predicate: Wenn der Wert für Predicate
null
ist (Standard), führt der Veröffentlichungsdienst für die Integritätsprüfung alle registrierten Integritätsprüfungen durch. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die die Menge der Prüfungen filtert. Das Prädikat wird in jedem Zeitraum ausgewertet. - Timeout: Hierbei handelt es sich um das Zeitlimit für die Ausführung der Integritätsprüfungen für alle IHealthCheckPublisher-Instanzen. Verwenden Sie InfiniteTimeSpan zur Ausführung ohne Timeout. Der Standardwert ist 30 Sekunden.
In der Beispiel-App ist ReadinessPublisher
eine IHealthCheckPublisher-Implementierung. Der Integritätsprüfungsstatus wird für jede Überprüfung auf folgenden Protokollebenen protokolliert:
- Information (LogInformation), wenn der Status der Integritätsprüfungen Healthy lautet.
- Fehler (LogError), wenn der Status Degraded oder Unhealthy lautet.
public class ReadinessPublisher : IHealthCheckPublisher
{
private readonly ILogger _logger;
public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
{
_logger = logger;
}
// The following example is for demonstration purposes only. Health Checks
// Middleware already logs health checks results. A real-world readiness
// check in a production app might perform a set of more expensive or
// time-consuming checks to determine if other resources are responding
// properly.
public Task PublishAsync(HealthReport report,
CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
_logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
else
{
_logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
cancellationToken.ThrowIfCancellationRequested();
return Task.CompletedTask;
}
}
Im Beispiel LivenessProbeStartup
der Beispiel-App StartupHostedService
hat die Bereitschaftsprüfung eine Startverzögerung von zwei Sekunden und führt die Prüfung alle 30 Sekunden aus. Zum Aktivieren der IHealthCheckPublisher Implementierung registriert das Beispiel ReadinessPublisher
als Singletondienst im Abhängigkeitsinjektionscontainer (Dependency Injection, DI):
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();
services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
Hinweis
AspNetCore.Diagnostics.HealthChecks
enthält Herausgeber für verschiedene Systeme, einschließlich Application Insights.
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Einschränken von Integritätsprüfungen mit MapWhen
Verwenden Sie MapWhen, um die Anforderungspipeline für Endpunkte von Integritätsprüfungen bedingt zu branchen.
Im folgenden Beispiel verzweigt MapWhen
die Anforderungspipeline so, dass die Middleware für Integritätsprüfungen aktiviert wird, wenn eine GET-Anforderung für den Endpunkt api/HealthCheck
empfangen wird:
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
Weitere Informationen finden Sie unter ASP.NET Core-Middleware.
ASP.NET Core bietet Middleware für Integritätsprüfungen und Bibliotheken für die Berichterstellung für Komponenten der App-Infrastruktur.
Integritätsprüfungen werden von einer App als HTTP-Endpunkte verfügbar gemacht. Endpunkte für die Integritätsprüfung können für verschiedene Echtzeitüberwachungsszenarien konfiguriert werden:
- Integritätstests können von Containerorchestratoren und Lastenausgleichsmodulen verwendet werden, um den Status einer App zu überprüfen. Ein Containerorchestrator kann z.B. auf eine fehlerhafte Integritätsprüfung reagieren, indem die Ausführung einer Bereitstellung angehalten oder ein Container neu gestartet wird. Ein Lastenausgleichsmodul kann auf eine fehlerhafte App reagieren, indem Datenverkehr von der fehlerhaften zu einer fehlerfreien Instanz umgeleitet wird.
- Die Nutzung von Arbeitsspeicher, Datenträgern und anderen physischen Serverressourcen kann auf einen fehlerfreien Status überwacht werden.
- Integritätsprüfungen können die Abhängigkeiten einer App testen, wie z.B. Datenbanken und externe Dienstendpunkte, um Verfügbarkeit und normale Funktionsweise zu bestätigen.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Die Beispiel-App enthält Beispiele der in diesem Artikel beschriebenen Szenarien. Um die Beispiel-App für ein bestimmtes Szenario auszuführen, verwenden Sie den Befehl dotnet run aus dem Ordner des Projekts in einer Befehlsshell. Informationen zur Verwendung der Beispiel-App finden Sie in der zugehörigen Datei README.md
und den Szenariobeschreibungen in diesem Artikel.
Voraussetzungen
Integritätsprüfungen werden in der Regel mit einem externen Überwachungsdienst oder Containerorchestrator verwendet, um den Status einer App zu überprüfen. Bevor Sie Integritätsprüfungen zu einer App hinzufügen, entscheiden Sie, welches Überwachungssystem verwendet werden soll. Das Überwachungssystem bestimmt, welche Arten von Integritätsprüfungen erstellt und wie die jeweiligen Endpunkte konfiguriert werden müssen.
Für ASP.NET Core-Apps wird implizit auf das Paket Microsoft.AspNetCore.Diagnostics.HealthChecks
verwiesen. Fügen Sie einen Verweis auf das Paket Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
hinzu, um Integritätsprüfungen mit Entity Framework Core durchzuführen.
Die Beispiel-App stellt Startcode bereit, um die Integritätsprüfungen für verschiedene Szenarien zu veranschaulichen. Das Szenario Datenbanktest überprüft die Integrität einer Datenbankverbindung mithilfe von AspNetCore.Diagnostics.HealthChecks
. Im Szenario DbContext-Test wird eine Datenbank mithilfe eines EF Core-DbContext
überprüft. Für ein Erkunden der Datenbankszenarios gilt für die Beispiel-App:
- Sie erstellt eine Datenbank und stellt deren Verbindungszeichenfolge in der
appsettings.json
-Datei bereit. - Sie hat die folgenden Paketverweise in ihrer Projektdatei:
Hinweis
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Ein anderes Szenario für Integritätsprüfungen zeigt, wie Sie Integritätsprüfungen auf einen Verwaltungsport filtern können. Für die Beispiel-App müssen Sie eine Properties/launchSettings.json
-Datei erstellen, die die Verwaltungs-URL und den Verwaltungsport enthält. Weitere Informationen finden Sie im Abschnitt Filtern nach Port.
Grundlegender Integritätstest
In vielen Apps genügt zur Ermittlung des App-Status eine grundlegende Integritätstestkonfiguration, die die Verfügbarkeit der App für die Verarbeitung von Anforderungen (Lebendigkeit) meldet.
Die grundlegende Konfiguration registriert Integritätsprüfungsdienste und ruft die Middleware für Integritätsprüfungen auf, damit diese an einem URL-Endpunkt mit dem Integritätsstatus antwortet. Standardmäßig werden keine spezifischen Integritätsprüfungen registriert, um eine bestimmte Abhängigkeit oder ein bestimmtes Subsystem zu testen. Die App wird als fehlerfrei angesehen, wenn sie an der URL des Integritätsendpunkts antworten kann. Der standardmäßig verwendete Antwortwriter schreibt den Status (HealthStatus) als Nur-Text-Antwort zurück an den Client und gibt dabei den Status HealthStatus.Healthy, HealthStatus.Degraded oder HealthStatus.Unhealthy an.
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Erstellen Sie einen Integritätsprüfungs-Endpunkt durch Aufrufen von MapHealthChecks
in Startup.Configure
.
In der Beispiel-App wird der Integritätsprüfungs-Endpunkt in /health
(BasicStartup.cs
) erstellt:
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
Um das Szenario für die grundlegende Konfiguration mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario basic
Docker-Beispiel
Docker bietet eine integrierte HEALTHCHECK
-Direktive, mit der Sie den Status einer App überprüfen können, die die grundlegende Konfiguration für Integritätsprüfungen verwendet:
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
Erstellen von Integritätsprüfungen
Integritätsprüfungen werden durch Implementieren der IHealthCheck-Schnittstelle erstellt. Die CheckHealthAsync-Methode gibt ein HealthCheckResult zurück, das die Integrität als Healthy
, Degraded
oder Unhealthy
angibt. Das Ergebnis wird als Klartextantwort mit einem konfigurierbaren Statuscode geschrieben (diese Konfiguration wird im Abschnitt Optionen für die Integritätsprüfung beschrieben). HealthCheckResult kann auch optionale Schlüssel-Wert-Paare zurückgeben.
Die folgende ExampleHealthCheck
-Klasse veranschaulicht das Layout einer Integritätsprüfung. Die Integritätsprüfungslogik wird in der CheckHealthAsync
-Methode platziert. Im folgenden Beispiel wird eine Dummyvariable healthCheckResultHealthy
auf true
festgelegt. Wenn der Wert von healthCheckResultHealthy
auf false
festgelegt ist, wird der HealthCheckResult.Unhealthy
-Status zurückgegeben.
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("An unhealthy result."));
}
}
Registrieren von Integritätsprüfungsdiensten
Der ExampleHealthCheck
-Typ wird mit AddCheck in Startup.ConfigureServices
den Integritätsprüfungsdiensten hinzugefügt:
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
Die in der folgenden Abbildung gezeigte AddCheck-Überladung legt den Fehlerstatus (HealthStatus) fest, der angegeben werden soll, wenn die Integritätsprüfung einen Fehler meldet. Wenn der Fehlerstatus auf null
(Standardwert) festgelegt ist, wird HealthStatus.Unhealthy gemeldet. Diese Überladung ist ein nützliches Szenario für Bibliotheksersteller: Bei einem Integritätsprüfungsfehler wird der durch die Bibliothek angegebene Fehlerstatus von der App erzwungen, wenn die Implementierung der Integritätsprüfung die Einstellung berücksichtigt.
Tags können zum Filtern von Integritätsprüfungen verwendet werden (dies wird im Abschnitt Filtern von Integritätsprüfungen genauer beschrieben).
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck kann auch eine Lambdafunktion ausführen. Im folgenden Beispiel wird der Name der Integritätsprüfung als Example
angegeben, und die Prüfung gibt immer einen fehlerfreien Status zurück:
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
Rufen Sie AddTypeActivatedCheck auf, um Argumente an die Implementierung einer Integritätsprüfung zu übergeben. Im folgenden Beispiel akzeptiert TestHealthCheckWithArgs
eine ganze Zahl und eine Zeichenfolge, wenn CheckHealthAsync aufgerufen wird:
private class TestHealthCheckWithArgs : IHealthCheck
{
public TestHealthCheckWithArgs(int i, string s)
{
I = i;
S = s;
}
public int I { get; set; }
public string S { get; set; }
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
CancellationToken cancellationToken = default)
{
...
}
}
TestHealthCheckWithArgs
wird durch Aufrufen von AddTypeActivatedCheck
mit der Übergabe der ganzen Zahl und der Zeichenfolge an die Implementierung registriert:
services.AddHealthChecks()
.AddTypeActivatedCheck<TestHealthCheckWithArgs>(
"test",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" },
args: new object[] { 5, "string" });
Verwenden von Integritätsprüfungsrouting
Rufen Sie in Startup.Configure
auf der Endpunkterstellung mit der Endpunkt-URL oder dem relativen Pfad MapHealthChecks
auf:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Anfordern des Hosts
Rufen Sie RequireHost
auf, um einen oder mehrere zugelassene Hosts für den Integritätsprüfungs-Endpunkt anzugeben. Hosts sollten Unicode anstelle von Punycode verwenden und können einen Port enthalten. Wenn keine Sammlung bereitgestellt wird, wird jeder Host akzeptiert.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});
Weitere Informationen finden Sie im Abschnitt Filtern nach Port.
Anfordern der Autorisierung
Rufen Sie RequireAuthorization
auf, um die Autorisierungsmiddleware auf dem Integritätsprüfungs-Anforderungsendpunkt auszuführen. Eine RequireAuthorization
-Überladung akzeptiert eine oder mehrere Autorisierungsrichtlinien. Wenn keine Richtlinie bereitgestellt wird, wird die standardmäßige Autorisierungsrichtlinie verwendet.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireAuthorization();
});
Aktivieren ursprungsübergreifender Anforderungen (CORS)
Obwohl das manuelle Ausführen von Integritätsprüfungen über einen Browser kein gängiges Szenario ist, kann CORS-Middleware durch Aufrufen von RequireCors
für Integritätsprüfungsendpunkte aktiviert werden. Eine RequireCors
-Überladung akzeptiert einen CORS-Richtliniengenerator-Delegaten (CorsPolicyBuilder
) oder einen Richtliniennamen. Wenn keine Richtlinie bereitgestellt wird, wird die standardmäßige CORS-Richtlinie verwendet. Weitere Informationen finden Sie unter Aktivieren ursprungsübergreifender Anforderungen (Cross-Origin Requests, CORS) in ASP.NET Core.
Optionen für die Integritätsprüfung
HealthCheckOptions ermöglichen die Anpassung des Verhaltens von Integritätsprüfungen:
- Filtern von Integritätsprüfungen
- Anpassen des HTTP-Statuscodes
- Unterdrücken von Cacheheadern
- Anpassen der Ausgabe
Filtern von Integritätsprüfungen
Standardmäßig führt die Middleware für Integritätsprüfungen alle registrierten Integritätsprüfungen aus. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die einen booleschen Wert an die Option Predicate zurückgibt. Im folgenden Beispiel wird die Bar
-Integritätsprüfung anhand ihres Tags (bar_tag
) in der Bedingungsanweisung der Funktion herausgefiltert. Dabei wird true
nur zurückgegeben, wenn die Tags-Eigenschaft der Integritätsprüfung mit foo_tag
oder baz_tag
übereinstimmt:
In Startup.ConfigureServices
:
services.AddHealthChecks()
.AddCheck("Foo", () =>
HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
.AddCheck("Bar", () =>
HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
.AddCheck("Baz", () =>
HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });
In Startup.Configure
filtert Predicate
die „Bar“-Integritätsprüfung heraus. Nur Foo und Baz werden ausgeführt:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
});
Anpassen des HTTP-Statuscodes
Verwenden Sie ResultStatusCodes, um die Zuordnung des Integritätsstatus zu HTTP-Statuscodes anzupassen. Die folgenden StatusCodes-Zuweisungen stellen die von der Middleware verwendeten Standardwerte dar. Ändern Sie die Statuscodewerte so, dass sie Ihren Anforderungen entsprechen.
In Startup.Configure
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
});
Unterdrücken von Cacheheadern
AllowCachingResponses steuert, ob die Middleware für Integritätsprüfungen einer Testantwort HTTP-Header hinzufügt, um das Zwischenspeichern von Antworten zu verhindern. Wenn der Wert false
(Standard) lautet, legt die Middleware die Header Cache-Control
, Expires
und Pragma
fest oder überschreibt sie, um eine Zwischenspeicherung der Antworten zu verhindern. Wenn der Wert true
lautet, ändert die Middleware die Cacheheader der Antwort nicht.
In Startup.Configure
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = true
});
});
Anpassen der Ausgabe
Legen Sie in Startup.Configure
die Option HealthCheckOptions.ResponseWriter auf einen Delegaten für das Schreiben der Antwort fest:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
});
Der Standarddelegat schreibt eine minimale Klartextantwort mit dem Zeichenfolgenwert HealthReport.Status
. Der folgende benutzerdefinierte Delegat gibt eine benutzerdefinierte JSON-Antwort aus.
Das erste Beispiel aus der Beispiel-App veranschaulicht die Verwendung von System.Text.Json:
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions
{
Indented = true
};
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartObject();
writer.WriteString("status", result.Status.ToString());
writer.WriteStartObject("results");
foreach (var entry in result.Entries)
{
writer.WriteStartObject(entry.Key);
writer.WriteString("status", entry.Value.Status.ToString());
writer.WriteString("description", entry.Value.Description);
writer.WriteStartObject("data");
foreach (var item in entry.Value.Data)
{
writer.WritePropertyName(item.Key);
JsonSerializer.Serialize(
writer, item.Value, item.Value?.GetType() ??
typeof(object));
}
writer.WriteEndObject();
writer.WriteEndObject();
}
writer.WriteEndObject();
writer.WriteEndObject();
}
var json = Encoding.UTF8.GetString(stream.ToArray());
return context.Response.WriteAsync(json);
}
}
Im zweiten Beispiel wird veranschaulicht, wie Newtonsoft.Json verwendet wird:
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json";
var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
return context.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
Kommentieren Sie in der Beispiel-App die Präprozessoranweisung SYSTEM_TEXT_JSON
in CustomWriterStartup.cs
aus, um die Newtonsoft.Json
-Version von WriteResponse
zu aktivieren.
Die Integritätsprüfungs-API bietet keine integrierte Unterstützung für komplexe JSON-Rückgabeformate, da das Format für Ihre Überwachungssystemauswahl spezifisch ist. Passen Sie die Antwort in den vorangehenden Beispielen nach Bedarf an. Weitere Informationen zur JSON-Serialisierung mit System.Text.Json
finden Sie unter Serialisieren und Deserialisieren von JSON in .NET.
Datenbanktest
Eine Integritätsprüfung kann eine Datenbankabfrage angeben, die als boolescher Test ausgeführt wird, um zu ermitteln, ob die Datenbank normal reagiert.
Die Beispiel-App verwendet AspNetCore.Diagnostics.HealthChecks
, eine Bibliothek für Integritätsprüfungen für ASP.NET Core-Apps, um eine Integritätsprüfung für eine SQL Server-Datenbank-Instanz auszuführen. AspNetCore.Diagnostics.HealthChecks
führt eine SELECT 1
-Abfrage in der Datenbank aus, um zu bestätigen, dass die Verbindung mit der Datenbank fehlerfrei ist.
Warnung
Wenn Sie die Datenbankverbindung mithilfe einer Abfrage überprüfen, wählen Sie eine Abfrage aus, die eine schnelle Antwort zurückgibt. Bei einer Abfrage besteht immer das Risiko, dass die Datenbank überladen und ihre Leistung beeinträchtigt wird. In den meisten Fällen ist es nicht notwendig, eine Testabfrage auszuführen. Es genügt zumeist, einfach erfolgreich eine Verbindung mit der Datenbank herzustellen. Wenn Sie eine Abfrage ausführen müssen, wählen Sie eine einfache SELECT-Abfrage aus, wie z.B. SELECT 1
.
Fügen Sie einen Paketverweis auf AspNetCore.HealthChecks.SqlServer
hinzu.
Geben Sie in der appsettings.json
-Datei der App eine gültige Zeichenfolge für die Datenbankverbindung an. Die App verwendet eine SQL Server-Datenbank namens HealthCheckSample
:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"IncludeScopes": "true"
}
},
"AllowedHosts": "*"
}
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Die Beispiel-App ruft die AddSqlServer
-Methode mit der Verbindungszeichenfolge der Datenbank (DbHealthStartup.cs
) auf:
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Um das Szenario für den Datenbanktest mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario db
Hinweis
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Entity Framework Core-DbContext-Test
Die DbContext
-Überprüfung bestätigt, dass die App mit der Datenbank kommunizieren kann, die für einen EF Core-DbContext
konfiguriert wurde. Die DbContext
Überprüfung wird in Apps unterstützt, für die gilt:
- In ihnen wird Entity Framework Core (EF Core) verwendet.
- Fügen Sie einen Paketverweis auf
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
hinzu.
AddDbContextCheck<TContext>
registriert eine Integritätsprüfung für einen DbContext
. Der DbContext
wird als der TContext
für die Methode bereitgestellt. Eine Überladung ist verfügbar, um den Fehlerstatus, Tags sowie eine benutzerdefinierte Testabfrage zu konfigurieren.
Standardmäßig:
- Der
DbContextHealthCheck
ruft dieCanConnectAsync
-Methode von EF Core auf. Sie können festlegen, welcher Vorgang ausgeführt wird, wenn die Integrität mitAddDbContextCheck
-Methodenüberladungen überprüft wird. - Der Name der Integritätsprüfung ist der Name des
TContext
-Typs.
In der Beispiel-App wird AppDbContext
für AddDbContextCheck
bereitgestellt und als Dienst in Startup.ConfigureServices
(DbContextHealthStartup.cs
) registriert:
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Stellen Sie sicher, dass die mit der Verbindungszeichenfolge angegebene Datenbank in der SQL Server-Instanz nicht vorhanden ist, um das DbContext
-Testszenario mithilfe der Beispiel-App ausführen zu können. Falls die Datenbank vorhanden ist, löschen Sie sie.
Führen Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell aus:
dotnet run --scenario dbcontext
Wenn die App ausgeführt wird, überprüfen Sie den Integritätsstatus, indem Sie in einem Browser eine Anforderung an den /health
-Endpunkt senden. Datenbank und AppDbContext
sind nicht vorhanden, also sendet die App die folgende Antwort:
Unhealthy
Fordern Sie die Beispiel-App auf, die Datenbank zu erstellen. Senden Sie eine /createdatabase
-Anforderung. Die App sendet die folgende Antwort:
Creating the database...
Done!
Navigate to /health to see the health status.
Senden Sie eine Anforderung an den /health
-Endpunkt. Datenbank und Kontext sind vorhanden, also sendet die App die folgende Antwort:
Healthy
Fordern Sie die Beispiel-App auf, die Datenbank zu löschen. Senden Sie eine /deletedatabase
-Anforderung. Die App sendet die folgende Antwort:
Deleting the database...
Done!
Navigate to /health to see the health status.
Senden Sie eine Anforderung an den /health
-Endpunkt. Die App meldet einen fehlerhaften Status:
Unhealthy
Separate Tests für Bereitschaft und Lebendigkeit
In einigen Hostingszenarien wird ein Integritätsprüfungspaar verwendet, mit dem zwischen zwei App-Status unterschieden wird:
- Bereitschaft gibt an, ob die App ordnungsgemäß ausgeführt wird, aber nicht für den Empfang von Anforderungen bereit ist.
- Livetest gibt an, ob eine App abgestürzt ist und neu gestartet werden muss.
Betrachten Sie das folgende Beispiel: Eine App muss eine große Konfigurationsdatei herunterladen, bevor sie für die Verarbeitung von Anforderungen bereit ist. Wir möchten nicht, dass die App neu gestartet wird, wenn der erste Download fehlschlägt, da die App mehrmals versuchen kann, die Datei herunterzuladen. Wir verwenden einen Livetest, um den Livezustand des Prozesses zu beschreiben. Weitere Überprüfungen erfolgen nicht. Außerdem soll verhindert werden, dass Anforderungen an die App gesendet werden, bevor die Konfigurationsdatei erfolgreich heruntergeladen wurde. Wir verwenden einen Bereitschaftstest, um den Status "nicht bereit" anzugeben, bis der Download erfolgreich durchgeführt wurde und die App für den Empfang von Anforderungen bereit ist.
Die Beispiel-App enthält eine Integritätsprüfung, um den Abschluss eines Starttasks mit langer Ausführungsdauer in einem gehosteten Dienst zu melden. StartupHostedServiceHealthCheck
macht die Eigenschaft StartupTaskCompleted
verfügbar, die der gehostete Dienst auf true
festlegen kann, wenn der Task mit langer Ausführungsdauer abgeschlossen ist (StartupHostedServiceHealthCheck.cs
):
public class StartupHostedServiceHealthCheck : IHealthCheck
{
private volatile bool _startupTaskCompleted = false;
public string Name => "slow_dependency_check";
public bool StartupTaskCompleted
{
get => _startupTaskCompleted;
set => _startupTaskCompleted = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
if (StartupTaskCompleted)
{
return Task.FromResult(
HealthCheckResult.Healthy("The startup task is finished."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("The startup task is still running."));
}
}
Der Hintergrundtask mit langer Ausführungsdauer wird von einem gehosteten Dienst (Services/StartupHostedService
) gestartet. Nach Abschluss des Tasks wird StartupHostedServiceHealthCheck.StartupTaskCompleted
auf true
festgelegt:
public class StartupHostedService : IHostedService, IDisposable
{
private readonly int _delaySeconds = 15;
private readonly ILogger _logger;
private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;
public StartupHostedService(ILogger<StartupHostedService> logger,
StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
{
_logger = logger;
_startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is starting.");
// Simulate the effect of a long-running startup task.
Task.Run(async () =>
{
await Task.Delay(_delaySeconds * 1000);
_startupHostedServiceHealthCheck.StartupTaskCompleted = true;
_logger.LogInformation("Startup Background Service has started.");
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is stopping.");
return Task.CompletedTask;
}
public void Dispose()
{
}
}
Die Integritätsprüfung wird mit AddCheck zusammen mit dem gehosteten Dienst in Startup.ConfigureServices
registriert. Da der gehostete Dienst die Eigenschaft in der Integritätsprüfung festlegen muss, wird die Integritätsprüfung ebenfalls im Dienstcontainer (LivenessProbeStartup.cs
) registriert:
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();
services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt. In der Beispiel-App wird der Integritätsprüfungs-Endpunkt erstellt unter:
/health/ready
für die Bereitschaftsprüfung. Die Bereitschaftsprüfung filtert auf Integritätsprüfungen mit demready
-Tag./health/live
für die Lebendigkeitsprüfung. Die Lebendigkeitsprüfung filtertStartupHostedServiceHealthCheck
durch Rückgabe vonfalse
inHealthCheckOptions.Predicate
heraus (weitere Informationen unter Filtern von Integritätsprüfungen).
Im folgenden Beispielcode gilt Folgendes:
- Die Bereitschaftsprüfung verwendet alle registrierten Überprüfungen mit dem Tag „Bereit“.
Predicate
schließt alle Überprüfungen aus und gibt 200-OK zurück.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Um das Szenario für die Konfiguration von Bereitschafts-/Lebendigkeitsprüfungen mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario liveness
Besuchen Sie /health/ready
mehrmals in einem Browser, bis 15 Sekunden verstrichen sind. Die Integritätsprüfung meldet während der ersten 15 Sekunden Unhealthy
. Nach 15 Sekunden meldet der Endpunkt Healthy
, was darauf hindeutet, dass die Ausführung des Tasks mit langer Ausführungsdauer durch den gehosteten Dienst abgeschlossen wurde.
In diesem Beispiel wird auch ein Integritätsprüfungsherausgeber erstellt (IHealthCheckPublisher-Implementierung), der die erste Bereitschaftsprüfung mit einer Verzögerung von zwei Sekunden ausführt. Weitere Informationen finden Sie im Abschnitt Herausgeber der Integritätsprüfung.
Kubernetes-Beispiel
Die Verwendung von Bereitschafts- und Lebendigkeitstests ist in Umgebungen wie Kubernetes sehr nützlich. In Kubernetes muss eine App möglicherweise zeitaufwendige Startaufgaben ausführen, bevor sie Anforderungen wie z. B. das Testen der Verfügbarkeit der zugrunde liegenden Datenbank erfüllt. Durch Verwendung separater Überprüfungen kann der Orchestrator unterscheiden, ob eine App funktioniert, aber noch nicht bereit ist, oder ob die App nicht gestartet wurde. Weitere Informationen zu Bereitschafts- und Lebendigkeitstests in Kubernetes finden Sie in der Kubernetes-Dokumentation unter Configure Liveness and Readiness Probes (Konfigurieren von Lebendigkeits- und Bereitschaftstests).
Das folgende Beispiel veranschaulicht die Konfiguration eines Bereitschaftstests in Kubernetes:
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /health/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
Metrikbasierter Test mit einem benutzerdefinierten Antwortwriter
Die Beispiel-App veranschaulicht eine Arbeitsspeicher-Integritätsprüfung mit einem benutzerdefinierten Antwortwriter.
MemoryHealthCheck
meldet einen beeinträchtigten Status, wenn die App mehr Arbeitsspeicher verwendet, als für den Schwellenwert festgelegt wurde (1 GB in der Beispiel-App). Das HealthCheckResult enthält Garbage Collector-Informationen (GC) für die App (MemoryHealthCheck.cs
):
public class MemoryHealthCheck : IHealthCheck
{
private readonly IOptionsMonitor<MemoryCheckOptions> _options;
public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
{
_options = options;
}
public string Name => "memory_check";
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var options = _options.Get(context.Registration.Name);
// Include GC information in the reported diagnostics.
var allocated = GC.GetTotalMemory(forceFullCollection: false);
var data = new Dictionary<string, object>()
{
{ "AllocatedBytes", allocated },
{ "Gen0Collections", GC.CollectionCount(0) },
{ "Gen1Collections", GC.CollectionCount(1) },
{ "Gen2Collections", GC.CollectionCount(2) },
};
var status = (allocated < options.Threshold) ?
HealthStatus.Healthy : context.Registration.FailureStatus;
return Task.FromResult(new HealthCheckResult(
status,
description: "Reports degraded status if allocated bytes " +
$">= {options.Threshold} bytes.",
exception: null,
data: data));
}
}
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Die Integritätsprüfung wird nicht durch Übergabe an AddCheck aktiviert, stattdessen wird MemoryHealthCheck
als Dienst registriert. Alle bei IHealthCheck registrierten Dienste stehen für die Dienste und Middleware für Integritätsprüfungen zur Verfügung. Es wird empfohlen, Integritätsprüfungsdienste als Singleton-Dienste zu registrieren.
In CustomWriterStartup.cs
der Beispiel-App:
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
Ein Integritätsprüfungs-Endpunkt wird durch Aufrufen von MapHealthChecks
in Startup.Configure
erstellt. Ein WriteResponse
-Delegat wird in der ResponseWriter-Eigenschaft angegeben, um eine benutzerdefinierte JSON-Antwort auszugeben, wenn die Integritätsprüfung ausgeführt wird:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
}
Der WriteResponse
-Delegat formatiert das CompositeHealthCheckResult
als JSON-Objekt und führt zu folgender JSON-Ausgabe für die Integritätsprüfungsantwort. Weitere Informationen finden Sie im Abschnitt Anpassen der Ausgabe.
Um den metrikbasierten Test mit benutzerdefinierter Ausgabe des Antwortwriters mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario writer
Hinweis
AspNetCore.Diagnostics.HealthChecks
enthält Szenarios für metrikbasierte Integritätsprüfungen, einschließlich Prüfungen des Datenträgerspeichers und Lebendigkeitsprüfungen mit Maximalwert.
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Filtern nach Port
Rufen Sie RequireHost
auf MapHealthChecks
mit einem URL-Muster auf, das einen Port angibt, um die an diesen Port gerichteten Integritätsprüfungsanforderungen einzuschränken. Dieser Ansatz wird normalerweise in einer Containerumgebung verfolgt, um einen Port für Überwachungsdienste verfügbar zu machen.
Die Beispiel-App konfiguriert den Port mithilfe des Umgebungsvariablen-Konfigurationsanbieters. Der Port wird in der Datei launchSettings.json
festgelegt und über eine Umgebungsvariable an den Konfigurationsanbieter übergeben. Sie müssen den Server auch so konfigurieren, dass er am Verwaltungsport auf Anforderungen lauscht.
Um die Beispiel-App zum Veranschaulichen der Konfiguration des Verwaltungsports zu verwenden, erstellen Sie die Datei launchSettings.json
in einem Properties
-Ordner.
Die folgende Properties/launchSettings.json
-Datei in der Beispiel-App ist in den Projektdateien der Beispiel-App nicht vorhanden und muss manuell erstellt werden:
{
"profiles": {
"SampleApp": {
"commandName": "Project",
"commandLineArgs": "",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
"ASPNETCORE_MANAGEMENTPORT": "5001"
},
"applicationUrl": "http://localhost:5000/"
}
}
}
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Startup.ConfigureServices
. Erstellen Sie einen Integritätsprüfungs-Endpunkt durch Aufrufen von MapHealthChecks
in Startup.Configure
.
In der Beispiel-App gibt ein Aufruf von RequireHost
auf dem Endpunkt in Startup.Configure
den Verwaltungsport aus der Konfiguration an:
endpoints.MapHealthChecks("/health")
.RequireHost($"*:{Configuration["ManagementPort"]}");
Endpunkte werden in der Beispiel-App in Startup.Configure
erstellt. Im folgenden Beispielcode gilt Folgendes:
- Die Bereitschaftsprüfung verwendet alle registrierten Überprüfungen mit dem Tag „Bereit“.
Predicate
schließt alle Überprüfungen aus und gibt 200-OK zurück.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Hinweis
Sie können vermeiden, die Datei launchSettings.json
in der Beispiel-App erstellen zu müssen, indem Sie den Verwaltungsport explizit im Code festlegen. Fügen Sie in Program.cs
an der Stelle, an der HostBuilder erstellt wird, einen Aufruf von ListenAnyIP hinzu, und geben Sie den Endpunkt des Verwaltungsports der App an. Geben Sie in Configure
von ManagementPortStartup.cs
den Verwaltungsport mit RequireHost
an:
Program.cs
:
return new HostBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5001);
})
.UseStartup(startupType);
})
.Build();
ManagementPortStartup.cs
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});
Um das Szenario für die Konfiguration des Verwaltungsports mithilfe der Beispiel-App auszuführen, verwenden Sie den folgenden Befehl aus dem Ordner des Projekts in einer Befehlsshell:
dotnet run --scenario port
Verteilen einer Integritätsprüfungsbibliothek
So verteilen Sie eine Integritätsprüfung als Bibliothek:
Schreiben Sie eine Integritätsprüfung, die die IHealthCheck-Schnittstelle als eigenständige Klasse implementiert. Die Klasse kann Abhängigkeitsinjektion (Dependency Injection, DI), Typaktivierung und benannte Optionen verwenden, um auf Konfigurationsdaten zuzugreifen.
In der Integritätsprüfungslogik von
CheckHealthAsync
gilt Folgendes:data1
unddata2
werden in der Methode verwendet, um die Integritätsprüfungslogik des Tests auszuführen.AccessViolationException
wird verarbeitet.
Wenn eine AccessViolationException auftritt, wird der FailureStatus mit dem HealthCheckResult zurückgegeben, damit Benutzer den Integritätsprüfungs-Fehlerstatus konfigurieren können.
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace SampleApp { public class ExampleHealthCheck : IHealthCheck { private readonly string _data1; private readonly int? _data2; public ExampleHealthCheck(string data1, int? data2) { _data1 = data1 ?? throw new ArgumentNullException(nameof(data1)); _data2 = data2 ?? throw new ArgumentNullException(nameof(data2)); } public async Task<HealthCheckResult> CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken) { try { return HealthCheckResult.Healthy(); } catch (AccessViolationException ex) { return new HealthCheckResult( context.Registration.FailureStatus, description: "An access violation occurred during the check.", exception: ex, data: null); } } } }
Schreiben Sie eine Erweiterungsmethode mit Parametern, die von der nutzenden App in ihrer
Startup.Configure
-Methode aufgerufen werden. Nehmen Sie im folgenden Beispiel die folgende Signatur für die Integritätsprüfungsmethode an:ExampleHealthCheck(string, string, int )
Die oben stehende Signatur gibt an, dass
ExampleHealthCheck
weitere Daten benötigt, um die Testlogik für die Integritätsprüfung zu verarbeiten. Die Daten werden für den Delegaten bereitgestellt, der zum Erstellen der Integritätsprüfungsinstanz verwendet wird, wenn die Integritätsprüfung bei einer Erweiterungsmethode registriert wird. Im folgenden Beispiel gibt der Aufrufer optional Folgendes an:- Name der Integritätsprüfung (
name
). Wenn der Wertnull
ist, wirdexample_health_check
verwendet. - string-Datenpunkt für die Integritätsprüfung (
data1
). - integer-Datenpunkt für die Integritätsprüfung (
data2
). Wenn der Wertnull
ist, wird1
verwendet. - Fehlerstatus (HealthStatus). Der Standardwert ist
null
. Wenn der Wertnull
ist, wird HealthStatus.Unhealthy für einen Fehlerstatus gemeldet. - Tags (
IEnumerable<string>
).
using System.Collections.Generic; using Microsoft.Extensions.Diagnostics.HealthChecks; public static class ExampleHealthCheckBuilderExtensions { const string DefaultName = "example_health_check"; public static IHealthChecksBuilder AddExampleHealthCheck( this IHealthChecksBuilder builder, string name = default, string data1, int data2 = 1, HealthStatus? failureStatus = default, IEnumerable<string> tags = default) { return builder.Add(new HealthCheckRegistration( name ?? DefaultName, sp => new ExampleHealthCheck(data1, data2), failureStatus, tags)); } }
- Name der Integritätsprüfung (
Herausgeber der Integritätsprüfung
Wenn dem Dienstcontainer ein IHealthCheckPublisher hinzugefügt wird, führt das Integritätsprüfungssystem Ihre Integritätsprüfungen regelmäßig aus und ruft PublishAsync
mit dem Ergebnis auf. Dies ist nützlich in einem Szenario mit pushbasiertem Integritätsüberwachungssystem, in dem jeder Prozess das Überwachungssystem regelmäßig aufrufen muss, um die Integrität zu bestimmen.
Die IHealthCheckPublisher-Schnittstelle weist eine einzige Methode auf:
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions ermöglichen Ihnen, Folgendes festzulegen:
- Delay: Hierbei handelt es sich um die angewendete anfängliche Verzögerung zwischen dem Start der App und der Ausführung von IHealthCheckPublisher-Instanzen. Die Verzögerung wird einmal beim Start angewendet und gilt nicht für die nachfolgenden Iterationen. Der Standardwert beträgt fünf Sekunden.
- Period: Hierbei handelt es sich um die Dauer der Ausführung von IHealthCheckPublisher. Der Standardwert ist 30 Sekunden.
- Predicate: Wenn der Wert für Predicate
null
ist (Standard), führt der Veröffentlichungsdienst für die Integritätsprüfung alle registrierten Integritätsprüfungen durch. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die die Menge der Prüfungen filtert. Das Prädikat wird in jedem Zeitraum ausgewertet. - Timeout: Hierbei handelt es sich um das Zeitlimit für die Ausführung der Integritätsprüfungen für alle IHealthCheckPublisher-Instanzen. Verwenden Sie InfiniteTimeSpan zur Ausführung ohne Timeout. Der Standardwert ist 30 Sekunden.
In der Beispiel-App ist ReadinessPublisher
eine IHealthCheckPublisher-Implementierung. Der Integritätsprüfungsstatus wird für jede Überprüfung auf folgenden Protokollebenen protokolliert:
- Information (LogInformation), wenn der Status der Integritätsprüfungen Healthy lautet.
- Fehler (LogError), wenn der Status Degraded oder Unhealthy lautet.
public class ReadinessPublisher : IHealthCheckPublisher
{
private readonly ILogger _logger;
public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
{
_logger = logger;
}
// The following example is for demonstration purposes only. Health Checks
// Middleware already logs health checks results. A real-world readiness
// check in a production app might perform a set of more expensive or
// time-consuming checks to determine if other resources are responding
// properly.
public Task PublishAsync(HealthReport report,
CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
_logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
else
{
_logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
cancellationToken.ThrowIfCancellationRequested();
return Task.CompletedTask;
}
}
Im Beispiel LivenessProbeStartup
der Beispiel-App StartupHostedService
hat die Bereitschaftsprüfung eine Startverzögerung von zwei Sekunden und führt die Prüfung alle 30 Sekunden aus. Zum Aktivieren der IHealthCheckPublisher Implementierung registriert das Beispiel ReadinessPublisher
als Singletondienst im Abhängigkeitsinjektionscontainer (Dependency Injection, DI):
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();
services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
Hinweis
AspNetCore.Diagnostics.HealthChecks
enthält Herausgeber für verschiedene Systeme, einschließlich Application Insights.
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Einschränken von Integritätsprüfungen mit MapWhen
Verwenden Sie MapWhen, um die Anforderungspipeline für Endpunkte von Integritätsprüfungen bedingt zu branchen.
Im folgenden Beispiel verzweigt MapWhen
die Anforderungspipeline so, dass die Middleware für Integritätsprüfungen aktiviert wird, wenn eine GET-Anforderung für den Endpunkt api/HealthCheck
empfangen wird:
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
Weitere Informationen finden Sie unter ASP.NET Core-Middleware.
ASP.NET Core bietet Middleware für Integritätsprüfungen und Bibliotheken für die Berichterstellung für Komponenten der App-Infrastruktur.
Integritätsprüfungen werden von einer App als HTTP-Endpunkte verfügbar gemacht. Endpunkte für die Integritätsprüfung können für verschiedene Echtzeitüberwachungsszenarien konfiguriert werden:
- Integritätstests können von Containerorchestratoren und Lastenausgleichsmodulen verwendet werden, um den Status einer App zu überprüfen. Ein Containerorchestrator kann z.B. auf eine fehlerhafte Integritätsprüfung reagieren, indem die Ausführung einer Bereitstellung angehalten oder ein Container neu gestartet wird. Ein Lastenausgleichsmodul kann auf eine fehlerhafte App reagieren, indem Datenverkehr von der fehlerhaften zu einer fehlerfreien Instanz umgeleitet wird.
- Die Nutzung von Arbeitsspeicher, Datenträgern und anderen physischen Serverressourcen kann auf einen fehlerfreien Status überwacht werden.
- Integritätsprüfungen können die Abhängigkeiten einer App testen, wie z.B. Datenbanken und externe Dienstendpunkte, um Verfügbarkeit und normale Funktionsweise zu bestätigen.
Integritätsprüfungen werden in der Regel mit einem externen Überwachungsdienst oder Containerorchestrator verwendet, um den Status einer App zu überprüfen. Bevor Sie Integritätsprüfungen zu einer App hinzufügen, entscheiden Sie, welches Überwachungssystem verwendet werden soll. Das Überwachungssystem bestimmt, welche Arten von Integritätsprüfungen erstellt und wie die jeweiligen Endpunkte konfiguriert werden müssen.
Grundlegender Integritätstest
In vielen Apps genügt zur Ermittlung des App-Status eine grundlegende Integritätstestkonfiguration, die die Verfügbarkeit der App für die Verarbeitung von Anforderungen (Lebendigkeit) meldet.
Die grundlegende Konfiguration registriert Integritätsprüfungsdienste und ruft die Middleware für Integritätsprüfungen auf, damit diese an einem URL-Endpunkt mit dem Integritätsstatus antwortet. Standardmäßig werden keine spezifischen Integritätsprüfungen registriert, um eine bestimmte Abhängigkeit oder ein bestimmtes Subsystem zu testen. Die App wird als fehlerfrei angesehen, wenn sie an der URL des Integritätsendpunkts antworten kann. Der Standardantwortwriter schreibt HealthStatus als Klartextantwort an den Client. HealthStatus
ist HealthStatus.Healthy, HealthStatus.Degraded oder HealthStatus.Unhealthy.
Registrieren Sie Integritätsprüfungsdienste mit AddHealthChecks in Program.cs
. Erstellen Sie einen Integritätsprüfungsendpunkt durch Aufrufen von MapHealthChecks.
Im folgenden Beispiel wird ein Integritätsprüfungsendpunkt unter /healthz
erstellt:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/healthz");
app.Run();
Docker HEALTHCHECK
Docker bietet eine integrierte HEALTHCHECK
-Direktive, mit der Sie den Status einer App überprüfen können, die die grundlegende Konfiguration für Integritätsprüfungen verwendet:
HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit
Das vorherige Beispiel verwendet curl
, um eine HTTP-Anforderung an den Integritätsprüfungsendpunkt bei /healthz
auszugeben. curl
ist nicht in den .NET Linux-Containerimages enthalten, kann aber hinzugefügt werden, indem das erforderliche Paket in der Dockerfile installiert wird. Container, die auf Alpine Linux basierende Images verwenden, können das enthaltene wget
anstelle von curl
verwenden.
Erstellen von Integritätsprüfungen
Integritätsprüfungen werden durch Implementieren der IHealthCheck-Schnittstelle erstellt. Die CheckHealthAsync-Methode gibt ein HealthCheckResult zurück, das die Integrität als Healthy
, Degraded
oder Unhealthy
angibt. Das Ergebnis wird als Klartextantwort mit einem konfigurierbaren Statuscode geschrieben. Die Konfiguration wird im Abschnitt Integritätsprüfungsoptionen beschrieben. HealthCheckResult kann auch optionale Schlüssel-Wert-Paare zurückgeben.
Das folgende Beispiel veranschaulicht das Layout einer Integritätsprüfung:
public class SampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
Die Integritätsprüfungslogik wird in der CheckHealthAsync-Methode platziert. Im vorherigen Beispiel wird die Dummyvariable isHealthy
auf true
festgelegt. Wenn der Wert von isHealthy
auf false
festgelegt ist, wird der HealthCheckRegistration.FailureStatus-Status zurückgegeben.
Wenn CheckHealthAsync während der Überprüfung eine Ausnahme auslöst, wird ein neues Element HealthReportEntry zurückgegeben, dessen HealthReportEntry.Status auf FailureStatus festgelegt ist. Dieser Status ist definiert durch AddCheck (weitere Informationen finden Sie im Abschnitt Registrieren von Diensten zur Integritätsprüfung) und enthält die innere Ausnahme, die den Prüfungsfehler verursacht hat. Description ist auf die Meldung der Ausnahme festgelegt.
Registrieren von Integritätsprüfungsdiensten
Rufen Sie AddCheck in Program.cs
auf, um einen Integritätsprüfungsdienst zu registrieren:
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>("Sample");
Die in der folgenden Abbildung gezeigte AddCheck-Überladung legt den Fehlerstatus (HealthStatus) fest, der angegeben werden soll, wenn die Integritätsprüfung einen Fehler meldet. Wenn der Fehlerstatus auf null
(Standardwert) festgelegt ist, wird HealthStatus.Unhealthy gemeldet. Diese Überladung ist ein nützliches Szenario für Bibliotheksersteller: Bei einem Integritätsprüfungsfehler wird der durch die Bibliothek angegebene Fehlerstatus von der App erzwungen, wenn die Implementierung der Integritätsprüfung die Einstellung berücksichtigt.
Tags können zum Filtern von Integritätsprüfungen verwendet werden. Tags werden im Abschnitt Filtern von Integritätsprüfungen beschrieben.
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" });
AddCheck kann auch eine Lambdafunktion ausführen. Im folgenden Beispiel gibt die Integritätsprüfung immer ein fehlerfreies Ergebnis zurück:
builder.Services.AddHealthChecks()
.AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));
Rufen Sie AddTypeActivatedCheck auf, um Argumente an die Implementierung einer Integritätsprüfung zu übergeben. Im folgenden Beispiel akzeptiert eine typaktivierte Integritätsprüfung in ihrem Konstruktor eine ganze Zahl und eine Zeichenfolge:
public class SampleHealthCheckWithArgs : IHealthCheck
{
private readonly int _arg1;
private readonly string _arg2;
public SampleHealthCheckWithArgs(int arg1, string arg2)
=> (_arg1, _arg2) = (arg1, arg2);
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
// ...
return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
}
}
Um die vorherige Integritätsprüfung zu registrieren, rufen Sie AddTypeActivatedCheck
mit der ganzen Zahl und der Zeichenfolge auf, die als Argumente übergeben werden:
builder.Services.AddHealthChecks()
.AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" },
args: new object[] { 1, "Arg" });
Verwenden von Integritätsprüfungsrouting
Rufen Sie in Program.cs
auf der Endpunkterstellung mit der Endpunkt-URL oder dem relativen Pfad MapHealthChecks
auf:
app.MapHealthChecks("/healthz");
Anfordern des Hosts
Rufen Sie RequireHost
auf, um einen oder mehrere zugelassene Hosts für den Integritätsprüfungs-Endpunkt anzugeben. Hosts sollten Unicode anstelle von Punycode verwenden und können einen Port enthalten. Wenn keine Sammlung bereitgestellt wird, wird jeder Host akzeptiert:
app.MapHealthChecks("/healthz")
.RequireHost("www.contoso.com:5001");
Um den Integritätsprüfungsendpunkt so einzuschränken, dass er nur an einem bestimmten Port antwortet, geben Sie beim Aufruf von RequireHost
einen Port an. Dieser Ansatz wird normalerweise in einer Containerumgebung verfolgt, um einen Port für Überwachungsdienste verfügbar zu machen:
app.MapHealthChecks("/healthz")
.RequireHost("*:5001");
Warnung
Die APIs, die auf dem Hostheader basieren, z. B. HttpRequest.Host und RequireHost, sind potenziellem Spoofing durch Clients ausgesetzt.
Verwenden Sie einen der folgenden Ansätze, um Host- und Portspoofing zu verhindern:
- Verwenden Sie HttpContext.Connection (ConnectionInfo.LocalPort), wobei die Ports aktiviert sind.
- Verwenden Sie die Hostfilterung.
Um zu verhindern, dass nicht autorisierte Clients den Port spoofen, rufen Sie RequireAuthorization auf:
app.MapHealthChecks("/healthz")
.RequireHost("*:5001")
.RequireAuthorization();
Weitere Informationen finden Sie unter Hostabgleich in Routen mit RequireHost.
Anfordern der Autorisierung
Rufen Sie RequireAuthorization auf, um die Autorisierungsmiddleware auf dem Integritätsprüfungs-Anforderungsendpunkt auszuführen. Eine RequireAuthorization
-Überladung akzeptiert eine oder mehrere Autorisierungsrichtlinien. Wenn keine Richtlinie bereitgestellt wird, wird die standardmäßige Autorisierungsrichtlinie verwendet:
app.MapHealthChecks("/healthz")
.RequireAuthorization();
Aktivieren ursprungsübergreifender Anforderungen (CORS)
Obwohl das manuelle Ausführen von Integritätsprüfungen über einen Browser kein gängiges Szenario ist, kann CORS-Middleware durch Aufrufen von RequireCors
für Integritätsprüfungsendpunkte aktiviert werden. Eine RequireCors
-Überladung akzeptiert einen CORS-Richtliniengenerator-Delegaten (CorsPolicyBuilder
) oder einen Richtliniennamen. Weitere Informationen finden Sie unter Aktivieren ursprungsübergreifender Anforderungen (Cross-Origin Requests, CORS) in ASP.NET Core.
Optionen für die Integritätsprüfung
HealthCheckOptions ermöglichen die Anpassung des Verhaltens von Integritätsprüfungen:
- Filtern von Integritätsprüfungen
- Anpassen des HTTP-Statuscodes
- Unterdrücken von Cacheheadern
- Anpassen der Ausgabe
Filtern von Integritätsprüfungen
Standardmäßig führt die Middleware für Integritätsprüfungen alle registrierten Integritätsprüfungen aus. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die einen booleschen Wert an die Option Predicate zurückgibt.
Im folgenden Beispiel werden die Integritätsprüfungen so gefiltert, dass nur die mit sample
gekennzeichneten ausgeführt werden:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});
Anpassen des HTTP-Statuscodes
Verwenden Sie ResultStatusCodes, um die Zuordnung des Integritätsstatus zu HTTP-Statuscodes anzupassen. Die folgenden StatusCodes-Zuweisungen stellen die von der Middleware verwendeten Standardwerte dar. Ändern Sie die Statuscodewerte so, dass sie Ihren Anforderungen entsprechen:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
Unterdrücken von Cacheheadern
AllowCachingResponses steuert, ob die Middleware für Integritätsprüfungen einer Testantwort HTTP-Header hinzufügt, um das Zwischenspeichern von Antworten zu verhindern. Wenn der Wert false
(Standard) lautet, legt die Middleware die Header Cache-Control
, Expires
und Pragma
fest oder überschreibt sie, um eine Zwischenspeicherung der Antworten zu verhindern. Wenn der Wert true
lautet, ändert die Middleware die Cacheheader der Antwort nicht:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
AllowCachingResponses = true
});
Anpassen der Ausgabe
Um die Ausgabe eines Integritätsprüfungsberichts anzupassen, legen Sie die Eigenschaft HealthCheckOptions.ResponseWriter für einen Delegaten fest, der die Antwort schreibt:
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResponseWriter = WriteResponse
});
Der Standarddelegat schreibt eine minimale Klartextantwort mit dem Zeichenfolgenwert HealthReport.Status
. Der folgende benutzerdefinierte Delegat gibt eine benutzerdefinierte JSON-Antwort mithilfe von System.Text.Json aus:
private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions { Indented = true };
using var memoryStream = new MemoryStream();
using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
{
jsonWriter.WriteStartObject();
jsonWriter.WriteString("status", healthReport.Status.ToString());
jsonWriter.WriteStartObject("results");
foreach (var healthReportEntry in healthReport.Entries)
{
jsonWriter.WriteStartObject(healthReportEntry.Key);
jsonWriter.WriteString("status",
healthReportEntry.Value.Status.ToString());
jsonWriter.WriteString("description",
healthReportEntry.Value.Description);
jsonWriter.WriteStartObject("data");
foreach (var item in healthReportEntry.Value.Data)
{
jsonWriter.WritePropertyName(item.Key);
JsonSerializer.Serialize(jsonWriter, item.Value,
item.Value?.GetType() ?? typeof(object));
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
return context.Response.WriteAsync(
Encoding.UTF8.GetString(memoryStream.ToArray()));
}
Die Integritätsprüfungs-API bietet keine integrierte Unterstützung für komplexe JSON-Rückgabeformate, da das Format für Ihre Überwachungssystemauswahl spezifisch ist. Passen Sie die Antwort in den vorangehenden Beispielen nach Bedarf an. Weitere Informationen zur JSON-Serialisierung mit System.Text.Json
finden Sie unter Serialisieren und Deserialisieren von JSON in .NET.
Datenbanktest
Eine Integritätsprüfung kann eine Datenbankabfrage angeben, die als boolescher Test ausgeführt wird, um zu ermitteln, ob die Datenbank normal reagiert.
AspNetCore.Diagnostics.HealthChecks
, eine Integritätsprüfungsbibliothek für ASP.NET Core-Apps, enthält eine Integritätsprüfung, die für eine SQL Server-Datenbank ausgeführt wird. AspNetCore.Diagnostics.HealthChecks
führt eine SELECT 1
-Abfrage in der Datenbank aus, um zu bestätigen, dass die Verbindung mit der Datenbank fehlerfrei ist.
Warnung
Wenn Sie die Datenbankverbindung mithilfe einer Abfrage überprüfen, wählen Sie eine Abfrage aus, die eine schnelle Antwort zurückgibt. Bei einer Abfrage besteht immer das Risiko, dass die Datenbank überladen und ihre Leistung beeinträchtigt wird. In den meisten Fällen ist es nicht notwendig, eine Testabfrage auszuführen. Es genügt zumeist, einfach erfolgreich eine Verbindung mit der Datenbank herzustellen. Wenn Sie eine Abfrage ausführen müssen, wählen Sie eine einfache SELECT-Abfrage aus, wie z.B. SELECT 1
.
Um diese SQL Server-Integritätsprüfung zu verwenden, fügen Sie einen Paketverweis auf das NuGet-Paket AspNetCore.HealthChecks.SqlServer
ein. Im folgenden Beispiel wird die SQL Server-Integritätsüberprüfung registriert:
builder.Services.AddHealthChecks()
.AddSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection"));
Hinweis
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Entity Framework Core-DbContext-Test
Die DbContext
-Überprüfung bestätigt, dass die App mit der Datenbank kommunizieren kann, die für einen EF Core-DbContext
konfiguriert wurde. Die DbContext
Überprüfung wird in Apps unterstützt, für die gilt:
- In ihnen wird Entity Framework Core (EF Core) verwendet.
- Fügen Sie einen Verweis auf das NuGet-Paket
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
ein.
AddDbContextCheck registriert eine Integritätsprüfung für einen DbContext. DbContext
wird der Methode als TContext
bereitgestellt. Eine Überladung ist verfügbar, um den Fehlerstatus, Tags sowie eine benutzerdefinierte Testabfrage zu konfigurieren.
Standardmäßig:
- Der
DbContextHealthCheck
ruft dieCanConnectAsync
-Methode von EF Core auf. Sie können festlegen, welcher Vorgang ausgeführt wird, wenn die Integrität mitAddDbContextCheck
-Methodenüberladungen überprüft wird. - Der Name der Integritätsprüfung ist der Name des
TContext
-Typs.
Im folgenden Beispiel werden ein DbContext
und ein zugeordneter DbContextHealthCheck
registriert:
builder.Services.AddDbContext<SampleDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddHealthChecks()
.AddDbContextCheck<SampleDbContext>();
Separate Tests für Bereitschaft und Lebendigkeit
In einigen Hostingszenarien wird ein Integritätsprüfungspaar verwendet, mit dem zwischen zwei App-Status unterschieden wird:
- Bereitschaft gibt an, ob die App ordnungsgemäß ausgeführt wird, aber nicht für den Empfang von Anforderungen bereit ist.
- Livetest gibt an, ob eine App abgestürzt ist und neu gestartet werden muss.
Betrachten Sie das folgende Beispiel: Eine App muss eine große Konfigurationsdatei herunterladen, bevor sie für die Verarbeitung von Anforderungen bereit ist. Wir möchten nicht, dass die App neu gestartet wird, wenn der erste Download fehlschlägt, da die App mehrmals versuchen kann, die Datei herunterzuladen. Wir verwenden einen Livetest, um den Livezustand des Prozesses zu beschreiben. Weitere Überprüfungen erfolgen nicht. Außerdem soll verhindert werden, dass Anforderungen an die App gesendet werden, bevor die Konfigurationsdatei erfolgreich heruntergeladen wurde. Wir verwenden einen Bereitschaftstest, um den Status "nicht bereit" anzugeben, bis der Download erfolgreich durchgeführt wurde und die App für den Empfang von Anforderungen bereit ist.
Die folgende Hintergrundaufgabe simuliert einen Startprozess, der ungefähr 15 Sekunden dauert. Nach Abschluss des Vorgangs legt die Aufgabe die StartupHealthCheck.StartupCompleted
-Eigenschaft auf TRUE fest:
public class StartupBackgroundService : BackgroundService
{
private readonly StartupHealthCheck _healthCheck;
public StartupBackgroundService(StartupHealthCheck healthCheck)
=> _healthCheck = healthCheck;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Simulate the effect of a long-running task.
await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);
_healthCheck.StartupCompleted = true;
}
}
StartupHealthCheck
meldet die Beendigung der lang ausgeführten Startaufgabe und macht die Eigenschaft StartupCompleted
verfügbar, die vom Hintergrunddienst festgelegt wird:
public class StartupHealthCheck : IHealthCheck
{
private volatile bool _isReady;
public bool StartupCompleted
{
get => _isReady;
set => _isReady = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
if (StartupCompleted)
{
return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
}
return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
}
}
Die Integritätsprüfung wird mit AddCheck zusammen mit dem gehosteten Dienst in Program.cs
registriert. Da der gehostete Dienst die Eigenschaft in der Integritätsprüfung festlegen muss, wird die Integritätsprüfung ebenfalls im Dienstcontainer als Singleton registriert:
builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();
builder.Services.AddHealthChecks()
.AddCheck<StartupHealthCheck>(
"Startup",
tags: new[] { "ready" });
Um zwei verschiedene Integritätsprüfungsendpunkte zu erstellen, rufen Sie MapHealthChecks
zweimal auf:
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
Predicate = _ => false
});
Im vorherigen Beispiel werden die folgenden Integritätsprüfungsendpunkte erstellt:
/healthz/ready
für die Bereitschaftsprüfung. Die Bereitschaftsprüfung filtert Integritätsprüfungen heraus, die mitready
gekennzeichnet sind./healthz/live
für die Lebendigkeitsprüfung. Die Liveüberprüfung filtert alle Integritätsprüfungen heraus, indemfalse
im Delegaten HealthCheckOptions.Predicate zurückgegeben wird. Weitere Informationen zum Filtern von Integritätsprüfungen finden Sie unter Filtern von Integritätsprüfungen in diesem Artikel.
Bevor die Startaufgabe abgeschlossen ist, meldet der Endpunkt /healthz/ready
den Status Unhealthy
. Bevor die Startaufgabe abgeschlossen ist, meldet dieser Endpunkt den Status Healthy
. Der Endpunkt /healthz/live
schließt alle Überprüfungen aus und meldet für alle Aufrufe den Status Healthy
.
Kubernetes-Beispiel
Die Verwendung von Bereitschafts- und Lebendigkeitstests ist in Umgebungen wie Kubernetes sehr nützlich. In Kubernetes muss eine App möglicherweise zeitaufwendige Startaufgaben ausführen, bevor sie Anforderungen wie z. B. das Testen der Verfügbarkeit der zugrunde liegenden Datenbank erfüllt. Durch Verwendung separater Überprüfungen kann der Orchestrator unterscheiden, ob eine App funktioniert, aber noch nicht bereit ist, oder ob die App nicht gestartet wurde. Weitere Informationen zu Bereitschafts- und Lebendigkeitstests in Kubernetes finden Sie in der Kubernetes-Dokumentation unter Configure Liveness and Readiness Probes (Konfigurieren von Lebendigkeits- und Bereitschaftstests).
Das folgende Beispiel veranschaulicht die Konfiguration eines Bereitschaftstests in Kubernetes:
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /healthz/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
Verteilen einer Integritätsprüfungsbibliothek
So verteilen Sie eine Integritätsprüfung als Bibliothek:
Schreiben Sie eine Integritätsprüfung, die die IHealthCheck-Schnittstelle als eigenständige Klasse implementiert. Die Klasse kann Abhängigkeitsinjektion (Dependency Injection, DI), Typaktivierung und benannte Optionen verwenden, um auf Konfigurationsdaten zuzugreifen.
Schreiben Sie eine Erweiterungsmethode mit Parametern, die von der nutzenden App in ihrer
Program.cs
-Methode aufgerufen werden. Betrachten Sie das folgende Beispiel einer Integritätsprüfung, diearg1
undarg2
als Konstruktorparameter akzeptiert:public SampleHealthCheckWithArgs(int arg1, string arg2) => (_arg1, _arg2) = (arg1, arg2);
Die vorherige Signatur gibt an, dass die Integritätsprüfung benutzerdefinierte Daten benötigt, um die Prüflogik der Integritätsprüfung zu verarbeiten. Die Daten werden für den Delegaten bereitgestellt, der zum Erstellen der Integritätsprüfungsinstanz verwendet wird, wenn die Integritätsprüfung bei einer Erweiterungsmethode registriert wird. Im folgenden Beispiel gibt der Aufrufer Folgendes an:
arg1
: ein integer-Datenpunkt für die Integritätsprüfung.arg2
: ein Zeichenfolgenargument für die Integritätsprüfung.name
: ein optionaler Name der Integritätsprüfung. Fallsnull
, wird ein Standardwert verwendet.failureStatus
: ein optionales Element HealthStatus, das bei einem Fehlerstatus gemeldet wird. Wenn der Wertnull
ist, wird HealthStatus.Unhealthy verwendet.tags
: eine optionaleIEnumerable<string>
-Sammlung von Tags.
public static class SampleHealthCheckBuilderExtensions { private const string DefaultName = "Sample"; public static IHealthChecksBuilder AddSampleHealthCheck( this IHealthChecksBuilder healthChecksBuilder, int arg1, string arg2, string? name = null, HealthStatus? failureStatus = null, IEnumerable<string>? tags = default) { return healthChecksBuilder.Add( new HealthCheckRegistration( name ?? DefaultName, _ => new SampleHealthCheckWithArgs(arg1, arg2), failureStatus, tags)); } }
Herausgeber der Integritätsprüfung
Wenn dem Dienstcontainer ein IHealthCheckPublisher hinzugefügt wird, führt das Integritätsprüfungssystem Ihre Integritätsprüfungen regelmäßig aus und ruft PublishAsync mit dem Ergebnis auf. Dieser Prozess ist nützlich in einem Szenario mit pushbasiertem Integritätsüberwachungssystem, in dem jeder Prozess das Überwachungssystem regelmäßig aufrufen muss, um Integrität zu bestimmen.
HealthCheckPublisherOptions ermöglichen Ihnen, Folgendes festzulegen:
- Delay: Hierbei handelt es sich um die angewendete anfängliche Verzögerung zwischen dem Start der App und der Ausführung von IHealthCheckPublisher-Instanzen. Die Verzögerung wird einmal beim Start angewendet und gilt nicht für spätere Iterationen. Der Standardwert beträgt fünf Sekunden.
- Period: Hierbei handelt es sich um die Dauer der Ausführung von IHealthCheckPublisher. Der Standardwert ist 30 Sekunden.
- Predicate: Wenn der Wert für Predicate
null
ist (Standard), führt der Veröffentlichungsdienst für die Integritätsprüfung alle registrierten Integritätsprüfungen durch. Um eine Teilmenge von Integritätsprüfungen auszuführen, stellen Sie eine Funktion bereit, die die Menge der Prüfungen filtert. Das Prädikat wird in jedem Zeitraum ausgewertet. - Timeout: Hierbei handelt es sich um das Zeitlimit für die Ausführung der Integritätsprüfungen für alle IHealthCheckPublisher-Instanzen. Verwenden Sie InfiniteTimeSpan zur Ausführung ohne Timeout. Der Standardwert ist 30 Sekunden.
Das folgende Beispiel veranschaulicht das Layout eines Integritätsprüfungsherausgebers:
public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
// ...
}
else
{
// ...
}
return Task.CompletedTask;
}
}
Die HealthCheckPublisherOptions-Klasse stellt Eigenschaften zum Konfigurieren des Verhaltens des Integritätsprüfungsherausgebers bereit.
Im folgenden Beispiel wird ein Integritätsprüfungsherausgeber als Singleton registriert und HealthCheckPublisherOptions konfiguriert:
builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});
builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();
Hinweis
AspNetCore.Diagnostics.HealthChecks
enthält Herausgeber für verschiedene Systeme, einschließlich Application Insights.
AspNetCore.Diagnostics.HealthChecks
wird nicht von Microsoft verwaltet oder unterstützt.
Abhängigkeitsinjektion und Integritätsprüfungen
Es ist möglich, eine Instanz eines bestimmten Type
innerhalb einer Integritätsprüfungsklasse über eine Abhängigkeitsinjektion zu verwenden. Die Abhängigkeitsinjektion kann hilfreich sein, um Optionen oder eine globale Konfiguration in eine Integritätsprüfung einzufügen. Die Verwendung der Abhängigkeitsinjektion ist kein gängiges Szenario zum Konfigurieren von Integritätsprüfungen. In der Regel ist jede Integritätsprüfung spezifisch für den tatsächlichen Test und wird mithilfe von IHealthChecksBuilder
-Erweiterungsmethoden konfiguriert.
Das folgende Beispiel zeigt ein Beispiel für eine Integritätsprüfung, die ein Konfigurationsobjekt über eine Abhängigkeitsinjektion abruft:
public class SampleHealthCheckWithDI : IHealthCheck
{
private readonly SampleHealthCheckWithDiConfig _config;
public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
=> _config = config;
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// use _config ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
SampleHealthCheckWithDiConfig
und die Integritätsprüfung müssen dem Dienstcontainer hinzugefügt werden:
builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheckWithDI>(
"With Dependency Injection",
tags: new[] { "inject" });
UseHealthChecks im Vergleich zu MapHealthChecks
Es gibt zwei Möglichkeiten, Integritätsprüfungen für Aufrufer zugänglich zu machen:
- UseHealthChecks registriert Middleware für die Verarbeitung von Integritätsprüfungsanforderungen in der Middlewarepipeline.
- MapHealthChecks registriert einen Integritätsprüfungsendpunkt. Der Endpunkt wird zusammen mit anderen Endpunkten in der App abgeglichen und ausgeführt.
Der Vorteil der Verwendung von MapHealthChecks
gegenüber UseHealthChecks
ist die Möglichkeit, endpunktfähige Middleware wie Autorisierung zu verwenden und eine präzisere Kontrolle über die Abgleichsrichtlinie zu haben. Der Hauptvorteil der Verwendung von UseHealthChecks
gegenüber MapHealthChecks
besteht darin, genau zu steuern, wo Integritätsprüfungen in der Middlewarepipeline ausgeführt werden.
- Beendet die Pipeline, wenn eine Anforderung mit dem Integritätsprüfungsendpunkt übereinstimmt. Kurzschlüsse sind häufig wünschenswert, da dadurch unnötige Arbeit vermieden wird, z. B. Protokollierung und andere Middleware.
- Wird in erster Linie zum Konfigurieren der Integritätsprüfungsmiddleware in der Pipeline verwendet.
- Kann einen beliebigen Pfad an einem Port mit einem
null
-Wert oder einem leerenPathString
-Wert abgleichen. Ermöglicht das Durchführen einer Integritätsprüfung für jede Anforderung, die an den angegebenen Port gestellt wird. - Quellcode
MapHealthChecks ermöglicht:
- Zuordnen bestimmter Routen oder Endpunkte für Integritätsprüfungen.
- Anpassen der URL oder des Pfads, unter der bzw. dem auf den Integritätsprüfungsendpunkt zugegriffen werden kann.
- Zuordnen mehrerer Integritätsprüfungsendpunkte mit unterschiedlichen Routen oder Konfigurationen. Unterstützung mehrerer Endpunkte:
- Aktiviert separate Endpunkte für verschiedene Arten von Integritätsprüfungen oder -komponenten.
- Wird verwendet, um zwischen verschiedenen Aspekten der App-Integrität zu unterscheiden oder bestimmte Konfigurationen auf Teilmengen von Integritätsprüfungen anzuwenden.
- Quellcode
Zusätzliche Ressourcen
Hinweis
Dieser Artikel wurde teilweise mit Hilfe künstlicher Intelligenz erstellt. Vor der Veröffentlichung hat ein Autor den Inhalt geprüft und nach Bedarf überarbeitet. Weitere Informationen finden Sie unter Unsere Prinzipien für die Verwendung von KI-generierten Inhalten in Microsoft Learn.