Comprobaciones de estado en ASP.NET Core
Por Glenn Condron
ASP.NET Core ofrece el middleware de comprobaciones de estado y bibliotecas para informar sobre el estado de los componentes de la infraestructura de la aplicación.
Una aplicación se encarga de exponer las comprobaciones de estado como puntos de conexión HTTP. Los puntos de conexión de las comprobaciones de estado pueden configurarse para diversos escenarios de supervisión en tiempo real:
- Los orquestadores de contenedores y los equilibradores de carga pueden utilizar los sondeos de estado para comprobar el estado de una aplicación. Por ejemplo, para responder a una comprobación de estado con errores, es posible que un orquestador de contenedores detenga una implementación en curso o reinicie un contenedor. Como respuesta a una aplicación con estado incorrecto, es posible que un equilibrador de carga enrute el tráfico al margen de la instancia con errores hacia una instancia con estado correcto.
- El uso de la memoria, el disco y otros recursos del servidor físico puede supervisarse para determinar si el estado es correcto.
- Las comprobaciones de estado pueden probar las dependencias de una aplicación, como las bases de datos y los puntos de conexión de servicio externo, para confirmar la disponibilidad y el funcionamiento normal.
Vea o descargue el código de ejemplo (cómo descargarlo)
La aplicación de muestra incluye ejemplos de los escenarios descritos en este tema. Para ejecutar la aplicación de ejemplo para un escenario determinado, use el comando dotnet run desde la carpeta del proyecto en un shell de comandos. Para obtener información sobre cómo utilizar la aplicación de ejemplo, consulte el archivo README.md de la aplicación de ejemplo y las descripciones de escenarios de este tema.
Requisitos previos
Normalmente, las comprobaciones de estado se usan con un servicio de supervisión externa o un orquestador de contenedores para comprobar el estado de una aplicación. Antes de agregar comprobaciones de estado a una aplicación, debe decidir en qué sistema de supervisión se va a usar. El sistema de supervisión determina qué tipos de comprobaciones de estado se deben crear y cómo configurar sus puntos de conexión.
Se ha referencia al paquete Microsoft.AspNetCore.Diagnostics.HealthChecks de forma implícita para las aplicaciones ASP.NET Core. Para realizar comprobaciones de estado con Entity Framework Core, agregue una referencia al paquete Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.
La aplicación de ejemplo proporciona código de inicio para mostrar las comprobaciones de estado para varios escenarios. En el escenario sondeo de base de datos se comprueba el estado de una conexión de base de datos mediante AspNetCore.Diagnostics.HealthChecks. El escenario sondeo de DbContext comprueba una base de datos mediante un elemento DbContext de EF Core. Para explorar los escenarios de la base de datos, la aplicación de ejemplo:
- Crea una base de datos y proporciona su cadena de conexión en el archivo
appsettings.json. - Tiene las siguientes referencias de paquete en su archivo de proyecto:
Nota
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Otro escenario de comprobación de estado muestra cómo filtrar las comprobaciones de estado por un puerto de administración. La aplicación de ejemplo requiere la creación de un archivo Properties/launchSettings.json que incluya la dirección URL de administración y el puerto de administración. Para obtener más información, consulte la sección Filtrado por puerto.
Sondeo de estado básico
Para muchas aplicaciones, una configuración de sondeo de estado básico que notifique la disponibilidad de la aplicación para procesar las solicitudes (ejecución) es suficiente para detectar el estado de la aplicación.
La configuración básica registra los servicios de comprobación de estado y llama al middleware de comprobaciones de estado para responder a un punto de conexión de dirección URL con una respuesta de estado. De forma predeterminada, no se registran comprobaciones de estado específicas para probar cualquier dependencia o subsistema concretos. La aplicación se considera correcta si es capaz de responder en la dirección URL de punto de conexión de estado. El escritor de respuesta predeterminado escribe el estado (HealthStatus) como respuesta de texto no cifrado al cliente, que indica un estado HealthStatus.Healthy, HealthStatus.Degraded o HealthStatus.Unhealthy.
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. Cree un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure.
En la aplicación de ejemplo, el punto de conexión de la comprobación de estado se crea en /health (BasicStartup.cs):
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
Para ejecutar el escenario de configuración básica mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario basic
Ejemplo de Docker
Docker ofrece una directiva de HEALTHCHECK integrada que puede utilizarse para comprobar el estado de una aplicación que use la configuración de comprobación de estado básica:
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
Creación de comprobaciones de estado
Las comprobaciones de estado se crean mediante la implementación de la interfaz de IHealthCheck. El método CheckHealthAsync devuelve un elemento HealthCheckResult que indica el estado como Healthy, Degraded o Unhealthy. El resultado se escribe como una respuesta de texto no cifrado con un código de estado configurable. (La configuración se describe en la sección Opciones de comprobación de estado). HealthCheckResult también puede devolver pares clave-valor opcionales.
La siguiente clase ExampleHealthCheck muestra el diseño de una comprobación de estado. La lógica de comprobaciones de estado se coloca en el método CheckHealthAsync. En el ejemplo siguiente se establece una variable ficticia, healthCheckResultHealthy, en true. Si el valor de healthCheckResultHealthy se establece en false, se devuelve el estado HealthCheckRegistration.FailureStatus.
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."));
}
}
Si CheckHealthAsync inicia una excepción durante la comprobación, se devuelve una nueva instancia de HealthReportEntry con HealthReportEntry.Status establecido en FailureStatus, que se define mediante AddCheck (vea la sección Registrar de servicios de comprobación de estado) e incluye la excepción interna que ha provocado inicialmente el error de comprobación. Description se establece en el mensaje de la excepción.
Registro de los servicios de comprobación de estado
El tipo ExampleHealthCheck se agrega a los servicios de comprobación de estado con AddCheck en Startup.ConfigureServices:
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
La sobrecarga AddCheck que se muestra en el ejemplo siguiente establece el estado de error (HealthStatus) para notificar cuándo la comprobación de estado informa de un error. Si el estado de error se establece en null (valor predeterminado), se notifica HealthStatus.Unhealthy. Esta sobrecarga es un escenario útil para los creadores de bibliotecas en los que la aplicación ejecuta el estado de error indicado por la biblioteca cuando se produce un error de comprobación de estado si la implementación de la comprobación de estado respeta la configuración.
Las etiquetas pueden usarse para filtrar las comprobaciones de estado, que se describen con más detalle en la sección Filtrado de las comprobaciones de estado.
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck también puede ejecutar una función lambda. En el ejemplo siguiente, el nombre de la comprobación de estado se especifica como Example y la comprobación siempre devuelve un estado correcto:
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
Llame a AddTypeActivatedCheck para pasar argumentos a una implementación de comprobación de estado. En el ejemplo siguiente, TestHealthCheckWithArgs acepta un entero y una cadena que se van a usar cuando se llame a CheckHealthAsync:
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 se registra mediante un llamado a AddTypeActivatedCheck con el entero y la cadena que se pasaron a la implementación:
services.AddHealthChecks()
.AddTypeActivatedCheck<TestHealthCheckWithArgs>(
"test",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" },
args: new object[] { 5, "string" });
Uso del enrutamiento de comprobaciones de estado
En Startup.Configure, llame a MapHealthChecks en el generador de puntos de conexiones con la dirección URL del punto de conexión o la ruta de acceso relativa:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Requerimiento de host
Llame RequireHost a para especificar uno o más hosts permitidos para el punto de conexión de comprobación de estado. Los hosts deben ser Unicode en lugar de Punycode y pueden incluir un puerto. Si no se proporciona una colección, se acepta cualquier host.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});
Para obtener más información, consulte la sección Filtrado por puerto.
Requerimiento de autorización
Llame a RequireAuthorization para ejecutar el middleware de autorización en el punto de conexión de solicitudes de comprobación de estado. Una sobrecarga RequireAuthorization acepta una o varias directivas de autorización. Si no se proporciona una directiva, se usa la directiva de autorización predeterminada.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireAuthorization();
});
Habilitar solicitudes entre orígenes (CORS)
Aunque no se suelen realizar comprobaciones de estado manualmente desde un explorador, el middleware de CORS se puede habilitar mediante una llamada a RequireCors en los puntos de conexión de las comprobaciones de estado. Una sobrecarga RequireCors acepta un delegado del generador de directivas CORS (CorsPolicyBuilder) o un nombre de directiva. Si no se proporciona una directiva, se usa la directiva CORS predeterminada. Para obtener más información, vea Habilitar solicitudes entre orígenes (CORS) en ASP.NET Core.
Opciones de comprobación de estado
El elemento HealthCheckOptions ofrece una oportunidad para personalizar el comportamiento de las comprobaciones de estado:
- Filtrado de las comprobaciones de estado
- Personalización del código de estado HTTP
- Supresión de los encabezados de caché
- Personalización del resultado
Filtrado de las comprobaciones de estado
De forma predeterminada, el middleware de comprobaciones de estado ejecuta todas las comprobaciones de estado registradas. Para ejecutar un subconjunto de comprobaciones de estado, proporcione una función que devuelva un valor booleano para la opción Predicate. En el ejemplo siguiente, la etiqueta (bar_tag) de la comprobación de estado Bar la filtra, en la instrucción condicional de la función, donde true solo se devuelve si la propiedad Tags de la comprobación de estado coincide con foo_tag o baz_tag:
En 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" });
En Startup.Configure, el Predicate filtra la comprobación de estado "Bar". Solo se ejecutan Foo y Baz:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
});
Personalización del código de estado HTTP
Use ResultStatusCodes para personalizar la asignación del estado de mantenimiento de los códigos de estado HTTP. Las siguientes asignaciones de StatusCodes son los valores predeterminados que el middleware utiliza. Cambie los valores de código de estado para satisfacer sus necesidades.
En Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
});
Supresión de los encabezados de caché
AllowCachingResponses controla si el middleware de comprobaciones de estado agrega encabezados HTTP a una respuesta de sondeo para evitar el almacenamiento en caché de respuesta. Si el valor es false (valor predeterminado), el middleware establece o invalida los encabezados Cache-Control, Expires y Pragma para evitar el almacenamiento en caché de respuesta. Si el valor es true, el middleware no modifica los encabezados de caché de la respuesta.
En Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = false
});
});
Personalización del resultado
En Startup.Configure, establezca la opción HealthCheckOptions.ResponseWriter en un delegado para escribir la respuesta:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
});
El delegado predeterminado escribe una respuesta de texto no cifrado mínima con el valor de cadena HealthReport.Status. Los siguientes delegados personalizados generan una respuesta JSON personalizada.
En el primer ejemplo de la aplicación de ejemplo se muestra cómo usar 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);
}
}
En el segundo ejemplo se muestra cómo usar Newtonsoft.Json:
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));
}
En la aplicación de ejemplo, convierta en comentario la directiva de preprocesador SYSTEM_TEXT_JSON en CustomWriterStartup.cs para habilitar la versión Newtonsoft.Json de WriteResponse.
La API de comprobaciones de estado no ofrece compatibilidad integrada con formatos de retorno JSON complejos porque el formato es específico del sistema de supervisión elegido. Personalice la respuesta en los ejemplos anteriores según sea necesario. Para más información sobre la serialización de JSON con System.Text.Json, consulte Procedimiento para serializar y deserializar JSON en .NET.
Sondeo de bases de datos
Una comprobación de estado puede especificar que una consulta de base de datos se ejecute como una prueba booleana para indicar si esta responde con normalidad.
En la aplicación de ejemplo se usa AspNetCore.Diagnostics.HealthChecks, una biblioteca de comprobaciones de estado para las aplicaciones de ASP.NET Core, a fin de realizar una comprobación de estado en una base de datos de SQL Server. AspNetCore.Diagnostics.HealthChecks ejecuta una consulta SELECT 1 en la base de datos para confirmar que la conexión a la base de datos es correcta.
Advertencia
Al comprobar la conexión de una base de datos a una consulta, elija una consulta que se devuelva rápidamente. El enfoque de la consulta plantea el riesgo de sobrecargar la base de datos y degradar el rendimiento. En la mayoría de los casos, no es necesario ejecutar una consulta de prueba. Simplemente, realizar una conexión correcta a la base de datos es suficiente. Si resulta necesario ejecutar una consulta, elija una consulta SELECT sencilla, como SELECT 1.
Incluya una referencia de paquete a AspNetCore.HealthChecks.SqlServer.
Proporcione una cadena de conexión a base de datos válida en el archivo appsettings.json de la aplicación de ejemplo. La aplicación usa una base de datos de SQL Server denominada 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": "*"
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. La aplicación de ejemplo llama al método AddSqlServer con la cadena de conexión de la base de datos (DbHealthStartup.cs):
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Para ejecutar el escenario de sondeo de base de datos mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario db
Nota
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Sondeo de DbContext de Entity Framework Core
La comprobación DbContext confirma que la aplicación puede comunicarse con la base de datos configurada para un elemento DbContext de EF Core. La comprobación DbContext se admite en las aplicaciones que:
- Usan Entity Framework (EF) Core.
- Incluya una referencia de paquete a
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.
AddDbContextCheck<TContext> registra una comprobación de estado para un elemento DbContext. El elemento DbContext se proporciona como TContext en el método. Hay disponible una sobrecarga para configurar el estado de error, las etiquetas y una consulta de prueba personalizada.
De manera predeterminada:
DbContextHealthCheckllama al métodoCanConnectAsyncde EF Core. Se puede personalizar qué operación se ejecuta al comprobar el estado con sobrecargas del métodoAddDbContextCheck.- El nombre de la comprobación de estado es el nombre del tipo
TContext.
En la aplicación de ejemplo, se proporciona AppDbContext para AddDbContextCheck y se registra como un servicio en Startup.ConfigureServices (DbContextHealthStartup.cs):
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Para ejecutar el escenario de sondeo de DbContext mediante la aplicación de ejemplo, confirme que la base de datos que la cadena de conexión especifica no exista en la instancia de SQL Server. Si la base de datos existe, elimínela.
Ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario dbcontext
Cuando la aplicación ya se esté ejecutando, compruebe el estado de mantenimiento mediante una solicitud al punto de conexión /health en un explorador. La base de datos y AppDbContext no existen, por lo que la aplicación proporciona la respuesta siguiente:
Unhealthy
Active la aplicación de ejemplo para crear la base de datos. Realice una solicitud a /createdatabase. La aplicación responde:
Creating the database...
Done!
Navigate to /health to see the health status.
Realice una solicitud al punto de conexión /health. La base de datos y el contexto existen, por lo que la aplicación responde:
Healthy
Active la aplicación de ejemplo para eliminar la base de datos. Realice una solicitud a /deletedatabase. La aplicación responde:
Deleting the database...
Done!
Navigate to /health to see the health status.
Realice una solicitud al punto de conexión /health. La aplicación proporciona una respuesta incorrecta:
Unhealthy
Sondeos de preparación y ejecución independientes
En algunos escenarios de hospedaje, se usa un par de comprobaciones de estado que distinguen los dos estados de la aplicación:
- Preparación indica si la aplicación se ejecuta con normalidad, pero no está lista para recibir solicitudes.
- Ejecución indica si una aplicación se ha bloqueado y debe reiniciarse.
Considere el ejemplo siguiente: Antes de estar lista para procesar solicitudes, una aplicación debe descargar un archivo de configuración de gran tamaño. No queremos que se reinicie la aplicación si se produce un error en la descarga inicial, dado que la aplicación puede volver a intentar descargar el archivo varias veces. Usamos un sondeo de ejecución para describir la ejecución del proceso, sin realizar ninguna otra comprobación. También queremos evitar que las solicitudes se envíen a la aplicación antes de que finalice la descarga del archivo de configuración. Hasta que no finaliza la descarga y la aplicación está lista para recibir solicitudes, usamos un sondeo de preparación para indicar un estado "no preparado".
La aplicación de ejemplo contiene una comprobación de estado para notificar la finalización de la tarea de inicio de ejecución prolongada en un servicio hospedado. El elemento StartupHostedServiceHealthCheck expone una propiedad, StartupTaskCompleted, que el servicio hospedado puede establecer en true al terminar su tarea de ejecución prolongada (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."));
}
}
Un servicio hospedado (Services/StartupHostedService) se encarga de iniciar la tarea en segundo plano de larga ejecución. Al finalizar la tarea, StartupHostedServiceHealthCheck.StartupTaskCompleted se establece en true:
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()
{
}
}
La comprobación de estado se registra con AddCheck en Startup.ConfigureServices junto con el servicio hospedado. Dado que el servicio hospedado debe establecer la propiedad en la comprobación de estado, esta también se registra en el contenedor de servicios (LivenessProbeStartup.cs):
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>();
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure. En la aplicación de ejemplo, los puntos de conexión de la comprobación de estado se crean en:
/health/readypara la comprobación de la idoneidad. La comprobación de preparación filtra las comprobaciones de estado con la etiquetaready./health/livepara la comprobación de la ejecución. La comprobación de ejecución filtra el elementoStartupHostedServiceHealthCheckmediante la devolución defalseenHealthCheckOptions.Predicate(para obtener más información, vea Filtrado de las comprobaciones de estado).
En el código de ejemplo siguiente:
- La comprobación de preparación usa todas las comprobaciones registradas con la etiqueta "ready".
Predicateexcluye todas las comprobaciones y devuelve una respuesta de que todo está correcto (200-OK).
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Para ejecutar el escenario de configuración de la preparación/ejecución mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario liveness
En un explorador, visite /health/ready varias veces hasta que hayan pasado 15 segundos. La comprobación de estado notifica un estado Unhealthy durante los primeros 15 segundos. Pasados 15 segundos, el punto de conexión notifica un estado Healthy, lo que indica que el servicio hospedado ya ha finalizado la tarea de ejecución prolongada.
En este ejemplo también se crea un publicador de la comprobación de estado (IHealthCheckPublisher implementación) que ejecuta la primera comprobación de preparación con un retraso de dos segundos. Para obtener más información, consulte la sección Publicador de la comprobación de estado.
Ejemplo de Kubernetes
Utilizar comprobaciones de preparación y ejecución independientes es útil en un entorno como Kubernetes. En Kubernetes, es posible que una aplicación deba realizar un trabajo de inicio que requiera mucho tiempo antes de aceptar solicitudes, como una prueba de la disponibilidad de la base de datos subyacente. El hecho de utilizar comprobaciones independientes permite que el orquestador distinga si la aplicación está funcionando, pero aún no esté preparada, o si la aplicación no se ha podido iniciar. Para obtener más información sobre los sondeos de preparación y ejecución en Kubernetes, consulte Configuración de sondeos de preparación y ejecución en la documentación de Kubernetes.
En el ejemplo siguiente, se muestra una configuración de sondeo de preparación de 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
Sondeo basado en métrica con un escritor de respuesta personalizada
La aplicación de ejemplo muestra una comprobación de estado de memoria con un escritor de respuesta personalizada.
MemoryHealthCheck notifica un estado degradado si la aplicación usa más de un umbral de memoria determinado (1 GB en la aplicación de ejemplo). El elemento HealthCheckResult incluye información del recolector de elementos no utilizados (GC) de la aplicación (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));
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. En lugar de pasar la comprobación de estado a AddCheck para habilitarla, MemoryHealthCheck se registra como servicio. Todos los servicios registrados de IHealthCheck están disponibles para los servicios de comprobación de estado y middleware. Se recomienda registrar los servicios de comprobación de estado como los servicios de Singleton.
En CustomWriterStartup.cs de la aplicación de ejemplo:
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure. Se proporciona un delegado WriteResponse a la propiedad <Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions.ResponseWriter> para generar una respuesta JSON personalizada cuando se ejecuta la comprobación de estado:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
}
El delegado WriteResponse da a CompositeHealthCheckResult el formato de objeto JSON y suspende el resultado de JSON para la respuesta de comprobación de estado. Para más información, consulte la sección Personalización del resultado.
Para ejecutar el sondeo basado en métrica con el resultado de un escritor de respuesta personalizada mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario writer
Nota
AspNetCore.Diagnostics.HealthChecks incluye escenarios de comprobación de estado basados en métricas, como las comprobaciones del almacenamiento del disco y de ejecución de máximo valor.
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Filtrado por puerto
Llame a RequireHost en MapHealthChecks con un patrón de dirección URL que especifique un puerto para restringir las solicitudes de comprobación de estado al puerto especificado. Esto se usa normalmente en un entorno de contenedor para exponer un puerto para los servicios de supervisión.
La aplicación de ejemplo configura el puerto con el proveedor de configuración de variable de entorno. El puerto se establece en el archivo launchSettings.json y se pasa al proveedor de configuración a través de una variable de entorno. También debe configurar el servidor para que escuche las solicitudes en el puerto de administración.
Para utilizar la aplicación de ejemplo para que muestre la configuración del puerto de administración, cree el archivo launchSettings.json en una carpeta Properties.
El archivo Properties/launchSettings.json siguiente de la aplicación de ejemplo no se incluye en los archivos de proyecto de la aplicación de ejemplo y se debe crear manualmente:
{
"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/"
}
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. Cree un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure.
En la aplicación de ejemplo, una llamada a RequireHost en el punto de conexión Startup.Configure especifica el puerto de administración de la configuración:
endpoints.MapHealthChecks("/health")
.RequireHost($"*:{Configuration["ManagementPort"]}");
Los puntos de conexión se crean en la aplicación de ejemplo en Startup.Configure. En el código de ejemplo siguiente:
- La comprobación de preparación usa todas las comprobaciones registradas con la etiqueta "ready".
Predicateexcluye todas las comprobaciones y devuelve una respuesta de que todo está correcto (200-OK).
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Nota
Para evitar la creación del archivo launchSettings.json en la aplicación de ejemplo, configure el puerto de administración explícitamente en código. En Program.cs, donde se crea HostBuilder, agregue una llamada a ListenAnyIP y proporcione el punto de conexión del puerto de administración de la aplicación. En Configure de ManagementPortStartup.cs, especifique el puerto de administración con RequireHost:
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");
});
Para ejecutar el escenario de configuración del puerto de administración mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario port
Distribución de una biblioteca de comprobación de estado
Para distribuir una comprobación de estado como una biblioteca, haga lo siguiente:
Escriba una comprobación de estado que implemente la interfaz de IHealthCheck como una clase independiente. La clase puede depender de la inserción de dependencias (DI), de la activación del tipo y de las opciones denominadas para acceder a los datos de configuración.
En la lógica de comprobaciones de estado de
CheckHealthAsync:data1ydata2se usan en el método para ejecutar la lógica de comprobación de estado del sondeo.- Se controla
AccessViolationException.
Cuando se produce un AccessViolationException, se devuelve FailureStatus con HealthCheckResult para permitir que los usuarios configuren el estado de error de las comprobaciones de estado.
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); } } } }Escriba un método de extensión con los parámetros a los que la aplicación de uso llama en su método
Startup.Configure. En el ejemplo siguiente, suponga que existe la siguiente firma del método de comprobación de estado:ExampleHealthCheck(string, string, int )La firma anterior indica que la
ExampleHealthCheckrequiere datos adicionales para procesar la lógica de sondeo de la comprobación de estado. Los datos se proporcionan al delegado que se usa para crear la instancia de la comprobación de estado cuando la comprobación de estado se registra con un método de extensión. En el ejemplo siguiente, el autor de llamada especifica los siguientes elementos opcionales:- nombre de la comprobación de estado (
name). En el caso denull, se utilizaexample_health_check. - punto de datos de cadena para la comprobación de estado (
data1). - punto de datos enteros para la comprobación de estado (
data2). En el caso denull, se utiliza1. - estado de error (HealthStatus). De manera predeterminada, es
null. Si esnull, se notificaHealthStatus.Unhealthypara un estado de error. - etiquetas (
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)); } }- nombre de la comprobación de estado (
Publicador de la comprobación de estado
Cuando un elemento IHealthCheckPublisher se agrega al contenedor de servicios, el sistema de comprobación de estado ejecuta periódicamente las comprobaciones de estado y llama a PublishAsync con el resultado. Esto es útil en un escenario de sistema de seguimiento de estado basado en inserción en el que se espera que cada proceso llame periódicamente al sistema de seguimiento con el fin de determinar el estado.
La interfaz de IHealthCheckPublisher tiene un único método:
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions le permiten establecer:
- Delay: el retraso inicial aplicado tras iniciarse la aplicación antes de ejecutar instancias de IHealthCheckPublisher. El retraso se aplica una vez durante el inicio y no se aplica a las iteraciones posteriores. El valor predeterminado es cinco segundos.
- Period: el período de ejecución de IHealthCheckPublisher. El valor predeterminado es 30 segundos.
- Predicate: si Predicate es
null(valor predeterminado), el servicio de publicador de la comprobación de estado ejecuta todas las comprobaciones de estado registradas. Para ejecutar un subconjunto de comprobaciones de estado, proporcione una función que filtre el conjunto de comprobaciones. El predicado se evalúa cada período. - Timeout: el tiempo de expiración para ejecutar las comprobaciones de estado para todas las instancias de IHealthCheckPublisher. Use InfiniteTimeSpan para ejecutar sin tiempo de expiración. El valor predeterminado es 30 segundos.
En la aplicación de ejemplo, ReadinessPublisher es una implementación de IHealthCheckPublisher. El estado de comprobación de estado se registra para cada comprobación en un nivel de registro de:
- Información (LogInformation) si el estado de las comprobaciones de estado es Healthy.
- Error (LogError) si el estado es Degraded o Unhealthy.
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;
}
}
En el ejemplo LivenessProbeStartup de la aplicación de ejemplo, la comprobación de preparación StartupHostedService tiene un retraso de inicio de dos segundos y ejecuta la comprobación cada 30 segundos. Para activar la implementación de IHealthCheckPublisher, el ejemplo registra ReadinessPublisher como servicio singleton en el contenedor de inserción de dependencias (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>();
Nota
AspNetCore.Diagnostics.HealthChecks incluye editores para varios sistemas, incluido Application Insights.
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Restricción de las comprobaciones de estado con MapWhen
Use MapWhen para crear de forma condicional una rama de la canalización de solicitudes para los puntos de conexión de comprobación del estado.
En el ejemplo siguiente, MapWhen crea una rama de la canalización de solicitudes para activar el middleware de comprobaciones de estado si se recibe una solicitud GET para el punto de conexión api/HealthCheck:
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
Para obtener más información, vea Middleware de ASP.NET Core.
ASP.NET Core ofrece el middleware de comprobaciones de estado y bibliotecas para informar sobre el estado de los componentes de la infraestructura de la aplicación.
Una aplicación se encarga de exponer las comprobaciones de estado como puntos de conexión HTTP. Los puntos de conexión de las comprobaciones de estado pueden configurarse para diversos escenarios de supervisión en tiempo real:
- Los orquestadores de contenedores y los equilibradores de carga pueden utilizar los sondeos de estado para comprobar el estado de una aplicación. Por ejemplo, para responder a una comprobación de estado con errores, es posible que un orquestador de contenedores detenga una implementación en curso o reinicie un contenedor. Como respuesta a una aplicación con estado incorrecto, es posible que un equilibrador de carga enrute el tráfico al margen de la instancia con errores hacia una instancia con estado correcto.
- El uso de la memoria, el disco y otros recursos del servidor físico puede supervisarse para determinar si el estado es correcto.
- Las comprobaciones de estado pueden probar las dependencias de una aplicación, como las bases de datos y los puntos de conexión de servicio externo, para confirmar la disponibilidad y el funcionamiento normal.
Vea o descargue el código de ejemplo (cómo descargarlo)
La aplicación de muestra incluye ejemplos de los escenarios descritos en este tema. Para ejecutar la aplicación de ejemplo para un escenario determinado, use el comando dotnet run desde la carpeta del proyecto en un shell de comandos. Para obtener información sobre cómo utilizar la aplicación de ejemplo, consulte el archivo README.md de la aplicación de ejemplo y las descripciones de escenarios de este tema.
Requisitos previos
Normalmente, las comprobaciones de estado se usan con un servicio de supervisión externa o un orquestador de contenedores para comprobar el estado de una aplicación. Antes de agregar comprobaciones de estado a una aplicación, debe decidir en qué sistema de supervisión se va a usar. El sistema de supervisión determina qué tipos de comprobaciones de estado se deben crear y cómo configurar sus puntos de conexión.
Se ha referencia al paquete Microsoft.AspNetCore.Diagnostics.HealthChecks de forma implícita para las aplicaciones ASP.NET Core. Para realizar comprobaciones de estado con Entity Framework Core, agregue una referencia al paquete Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.
La aplicación de ejemplo proporciona código de inicio para mostrar las comprobaciones de estado para varios escenarios. En el escenario sondeo de base de datos se comprueba el estado de una conexión de base de datos mediante AspNetCore.Diagnostics.HealthChecks. El escenario sondeo de DbContext comprueba una base de datos mediante un elemento DbContext de EF Core. Para explorar los escenarios de la base de datos, la aplicación de ejemplo:
- Crea una base de datos y proporciona su cadena de conexión en el archivo
appsettings.json. - Tiene las siguientes referencias de paquete en su archivo de proyecto:
Nota
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Otro escenario de comprobación de estado muestra cómo filtrar las comprobaciones de estado por un puerto de administración. La aplicación de ejemplo requiere la creación de un archivo Properties/launchSettings.json que incluya la dirección URL de administración y el puerto de administración. Para obtener más información, consulte la sección Filtrado por puerto.
Sondeo de estado básico
Para muchas aplicaciones, una configuración de sondeo de estado básico que notifique la disponibilidad de la aplicación para procesar las solicitudes (ejecución) es suficiente para detectar el estado de la aplicación.
La configuración básica registra los servicios de comprobación de estado y llama al middleware de comprobaciones de estado para responder a un punto de conexión de dirección URL con una respuesta de estado. De forma predeterminada, no se registran comprobaciones de estado específicas para probar cualquier dependencia o subsistema concretos. La aplicación se considera correcta si es capaz de responder en la dirección URL de punto de conexión de estado. El escritor de respuesta predeterminado escribe el estado (HealthStatus) como respuesta de texto no cifrado en el cliente, que indica un estado HealthStatus.Healthy, HealthStatus.Degraded o HealthStatus.Unhealthy.
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. Cree un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure.
En la aplicación de ejemplo, el punto de conexión de la comprobación de estado se crea en /health (BasicStartup.cs):
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
Para ejecutar el escenario de configuración básica mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario basic
Ejemplo de Docker
Docker ofrece una directiva de HEALTHCHECK integrada que puede utilizarse para comprobar el estado de una aplicación que use la configuración de comprobación de estado básica:
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
Creación de comprobaciones de estado
Las comprobaciones de estado se crean mediante la implementación de la interfaz de IHealthCheck. El método CheckHealthAsync devuelve un elemento HealthCheckResult que indica el estado como Healthy, Degraded o Unhealthy. El resultado se escribe como una respuesta de texto no cifrado con un código de estado configurable. (La configuración se describe en la sección Opciones de comprobación de estado). HealthCheckResult también puede devolver pares clave-valor opcionales.
La siguiente clase ExampleHealthCheck muestra el diseño de una comprobación de estado. La lógica de comprobaciones de estado se coloca en el método CheckHealthAsync. En el ejemplo siguiente se establece una variable ficticia, healthCheckResultHealthy, en true. Si el valor de healthCheckResultHealthy se establece en false, se devuelve el estado HealthCheckResult.Unhealthy.
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."));
}
}
Registro de los servicios de comprobación de estado
El tipo ExampleHealthCheck se agrega a los servicios de comprobación de estado con AddCheck en Startup.ConfigureServices:
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
La sobrecarga AddCheck que se muestra en el ejemplo siguiente establece el estado de error (HealthStatus) para notificar cuándo la comprobación de estado informa de un error. Si el estado de error se establece en null (valor predeterminado), se notifica HealthStatus.Unhealthy. Esta sobrecarga es un escenario útil para los creadores de bibliotecas en los que la aplicación ejecuta el estado de error indicado por la biblioteca cuando se produce un error de comprobación de estado si la implementación de la comprobación de estado respeta la configuración.
Las etiquetas pueden usarse para filtrar las comprobaciones de estado, que se describen con más detalle en la sección Filtrado de las comprobaciones de estado.
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck también puede ejecutar una función lambda. En el ejemplo siguiente, el nombre de la comprobación de estado se especifica como Example y la comprobación siempre devuelve un estado correcto:
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
Llame a AddTypeActivatedCheck para pasar argumentos a una implementación de comprobación de estado. En el ejemplo siguiente, TestHealthCheckWithArgs acepta un entero y una cadena que se van a usar cuando se llame a CheckHealthAsync:
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 se registra mediante un llamado a AddTypeActivatedCheck con el entero y la cadena que se pasaron a la implementación:
services.AddHealthChecks()
.AddTypeActivatedCheck<TestHealthCheckWithArgs>(
"test",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" },
args: new object[] { 5, "string" });
Uso del enrutamiento de comprobaciones de estado
En Startup.Configure, llame a MapHealthChecks en el generador de puntos de conexiones con la dirección URL del punto de conexión o la ruta de acceso relativa:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Requerimiento de host
Llame RequireHost a para especificar uno o más hosts permitidos para el punto de conexión de comprobación de estado. Los hosts deben ser Unicode en lugar de Punycode y pueden incluir un puerto. Si no se proporciona una colección, se acepta cualquier host.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});
Para obtener más información, consulte la sección Filtrado por puerto.
Requerimiento de autorización
Llame a RequireAuthorization para ejecutar el middleware de autorización en el punto de conexión de solicitudes de comprobación de estado. Una sobrecarga RequireAuthorization acepta una o varias directivas de autorización. Si no se proporciona una directiva, se usa la directiva de autorización predeterminada.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireAuthorization();
});
Habilitar solicitudes entre orígenes (CORS)
Aunque no se suelen realizar comprobaciones de estado manualmente desde un explorador, el middleware de CORS se puede habilitar mediante una llamada a RequireCors en los puntos de conexión de las comprobaciones de estado. Una sobrecarga RequireCors acepta un delegado del generador de directivas CORS (CorsPolicyBuilder) o un nombre de directiva. Si no se proporciona una directiva, se usa la directiva CORS predeterminada. Para obtener más información, vea Habilitar solicitudes entre orígenes (CORS) en ASP.NET Core.
Opciones de comprobación de estado
El elemento HealthCheckOptions ofrece una oportunidad para personalizar el comportamiento de las comprobaciones de estado:
- Filtrado de las comprobaciones de estado
- Personalización del código de estado HTTP
- Supresión de los encabezados de caché
- Personalización del resultado
Filtrado de las comprobaciones de estado
De forma predeterminada, el middleware de comprobaciones de estado ejecuta todas las comprobaciones de estado registradas. Para ejecutar un subconjunto de comprobaciones de estado, proporcione una función que devuelva un valor booleano para la opción Predicate. En el ejemplo siguiente, la etiqueta (bar_tag) de la comprobación de estado Bar la filtra, en la instrucción condicional de la función, donde true solo se devuelve si la propiedad Tags de la comprobación de estado coincide con foo_tag o baz_tag:
En 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" });
En Startup.Configure, el Predicate filtra la comprobación de estado "Bar". Solo se ejecutan Foo y Baz:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
});
Personalización del código de estado HTTP
Use ResultStatusCodes para personalizar la asignación del estado de mantenimiento de los códigos de estado HTTP. Las siguientes asignaciones de StatusCodes son los valores predeterminados que el middleware utiliza. Cambie los valores de código de estado para satisfacer sus necesidades.
En Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
});
Supresión de los encabezados de caché
AllowCachingResponses controla si el middleware de comprobaciones de estado agrega encabezados HTTP a una respuesta de sondeo para evitar el almacenamiento en caché de respuesta. Si el valor es false (valor predeterminado), el middleware establece o invalida los encabezados Cache-Control, Expires y Pragma para evitar el almacenamiento en caché de respuesta. Si el valor es true, el middleware no modifica los encabezados de caché de la respuesta.
En Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = false
});
});
Personalización del resultado
En Startup.Configure, establezca la opción HealthCheckOptions.ResponseWriter en un delegado para escribir la respuesta:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
});
El delegado predeterminado escribe una respuesta de texto no cifrado mínima con el valor de cadena HealthReport.Status. Los siguientes delegados personalizados generan una respuesta JSON personalizada.
En el primer ejemplo de la aplicación de ejemplo se muestra cómo usar 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);
}
}
En el segundo ejemplo se muestra cómo usar Newtonsoft.Json:
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));
}
En la aplicación de ejemplo, convierta en comentario la directiva de preprocesador SYSTEM_TEXT_JSON en CustomWriterStartup.cs para habilitar la versión Newtonsoft.Json de WriteResponse.
La API de comprobaciones de estado no ofrece compatibilidad integrada con formatos de retorno JSON complejos porque el formato es específico del sistema de supervisión elegido. Personalice la respuesta en los ejemplos anteriores según sea necesario. Para más información sobre la serialización de JSON con System.Text.Json, consulte Procedimiento para serializar y deserializar JSON en .NET.
Sondeo de bases de datos
Una comprobación de estado puede especificar que una consulta de base de datos se ejecute como una prueba booleana para indicar si esta responde con normalidad.
En la aplicación de ejemplo se usa AspNetCore.Diagnostics.HealthChecks, una biblioteca de comprobaciones de estado para las aplicaciones de ASP.NET Core, a fin de realizar una comprobación de estado en una base de datos de SQL Server. AspNetCore.Diagnostics.HealthChecks ejecuta una consulta SELECT 1 en la base de datos para confirmar que la conexión a la base de datos es correcta.
Advertencia
Al comprobar la conexión de una base de datos a una consulta, elija una consulta que se devuelva rápidamente. El enfoque de la consulta plantea el riesgo de sobrecargar la base de datos y degradar el rendimiento. En la mayoría de los casos, no es necesario ejecutar una consulta de prueba. Simplemente, realizar una conexión correcta a la base de datos es suficiente. Si resulta necesario ejecutar una consulta, elija una consulta SELECT sencilla, como SELECT 1.
Incluya una referencia de paquete a AspNetCore.HealthChecks.SqlServer.
Proporcione una cadena de conexión a base de datos válida en el archivo appsettings.json de la aplicación de ejemplo. La aplicación usa una base de datos de SQL Server denominada 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": "*"
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. La aplicación de ejemplo llama al método AddSqlServer con la cadena de conexión de la base de datos (DbHealthStartup.cs):
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Para ejecutar el escenario de sondeo de base de datos mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario db
Nota
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Sondeo de DbContext de Entity Framework Core
La comprobación DbContext confirma que la aplicación puede comunicarse con la base de datos configurada para un elemento DbContext de EF Core. La comprobación DbContext se admite en las aplicaciones que:
- Usan Entity Framework (EF) Core.
- Incluya una referencia de paquete a
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.
AddDbContextCheck<TContext> registra una comprobación de estado para un elemento DbContext. El elemento DbContext se proporciona como TContext en el método. Hay disponible una sobrecarga para configurar el estado de error, las etiquetas y una consulta de prueba personalizada.
De manera predeterminada:
DbContextHealthCheckllama al métodoCanConnectAsyncde EF Core. Se puede personalizar qué operación se ejecuta al comprobar el estado con sobrecargas del métodoAddDbContextCheck.- El nombre de la comprobación de estado es el nombre del tipo
TContext.
En la aplicación de ejemplo, se proporciona AppDbContext para AddDbContextCheck y se registra como un servicio en Startup.ConfigureServices (DbContextHealthStartup.cs):
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
Para ejecutar el escenario de sondeo de DbContext mediante la aplicación de ejemplo, confirme que la base de datos que la cadena de conexión especifica no exista en la instancia de SQL Server. Si la base de datos existe, elimínela.
Ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario dbcontext
Cuando la aplicación ya se esté ejecutando, compruebe el estado de mantenimiento mediante una solicitud al punto de conexión /health en un explorador. La base de datos y AppDbContext no existen, por lo que la aplicación proporciona la respuesta siguiente:
Unhealthy
Active la aplicación de ejemplo para crear la base de datos. Realice una solicitud a /createdatabase. La aplicación responde:
Creating the database...
Done!
Navigate to /health to see the health status.
Realice una solicitud al punto de conexión /health. La base de datos y el contexto existen, por lo que la aplicación responde:
Healthy
Active la aplicación de ejemplo para eliminar la base de datos. Realice una solicitud a /deletedatabase. La aplicación responde:
Deleting the database...
Done!
Navigate to /health to see the health status.
Realice una solicitud al punto de conexión /health. La aplicación proporciona una respuesta incorrecta:
Unhealthy
Sondeos de preparación y ejecución independientes
En algunos escenarios de hospedaje, se usa un par de comprobaciones de estado que distinguen los dos estados de la aplicación:
- Preparación indica si la aplicación se ejecuta con normalidad, pero no está lista para recibir solicitudes.
- Ejecución indica si una aplicación se ha bloqueado y debe reiniciarse.
Considere el ejemplo siguiente: Antes de estar lista para procesar solicitudes, una aplicación debe descargar un archivo de configuración de gran tamaño. No queremos que se reinicie la aplicación si se produce un error en la descarga inicial, dado que la aplicación puede volver a intentar descargar el archivo varias veces. Usamos un sondeo de ejecución para describir la ejecución del proceso, sin realizar ninguna otra comprobación. También queremos evitar que las solicitudes se envíen a la aplicación antes de que finalice la descarga del archivo de configuración. Hasta que no finaliza la descarga y la aplicación está lista para recibir solicitudes, usamos un sondeo de preparación para indicar un estado "no preparado".
La aplicación de ejemplo contiene una comprobación de estado para notificar la finalización de la tarea de inicio de ejecución prolongada en un servicio hospedado. El elemento StartupHostedServiceHealthCheck expone una propiedad, StartupTaskCompleted, que el servicio hospedado puede establecer en true al terminar su tarea de ejecución prolongada (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."));
}
}
Un servicio hospedado (Services/StartupHostedService) se encarga de iniciar la tarea en segundo plano de larga ejecución. Al finalizar la tarea, StartupHostedServiceHealthCheck.StartupTaskCompleted se establece en true:
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()
{
}
}
La comprobación de estado se registra con AddCheck en Startup.ConfigureServices junto con el servicio hospedado. Dado que el servicio hospedado debe establecer la propiedad en la comprobación de estado, esta también se registra en el contenedor de servicios (LivenessProbeStartup.cs):
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>();
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure. En la aplicación de ejemplo, los puntos de conexión de la comprobación de estado se crean en:
/health/readypara la comprobación de la idoneidad. La comprobación de preparación filtra las comprobaciones de estado con la etiquetaready./health/livepara la comprobación de la ejecución. La comprobación de ejecución filtra el elementoStartupHostedServiceHealthCheckmediante la devolución defalseenHealthCheckOptions.Predicate(para obtener más información, vea Filtrado de las comprobaciones de estado).
En el código de ejemplo siguiente:
- La comprobación de preparación usa todas las comprobaciones registradas con la etiqueta "ready".
Predicateexcluye todas las comprobaciones y devuelve una respuesta de que todo está correcto (200-OK).
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Para ejecutar el escenario de configuración de la preparación/ejecución mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario liveness
En un explorador, visite /health/ready varias veces hasta que hayan pasado 15 segundos. La comprobación de estado notifica un estado Unhealthy durante los primeros 15 segundos. Pasados 15 segundos, el punto de conexión notifica un estado Healthy, lo que indica que el servicio hospedado ya ha finalizado la tarea de ejecución prolongada.
En este ejemplo también se crea un publicador de la comprobación de estado (IHealthCheckPublisher implementación) que ejecuta la primera comprobación de preparación con un retraso de dos segundos. Para obtener más información, consulte la sección Publicador de la comprobación de estado.
Ejemplo de Kubernetes
Utilizar comprobaciones de preparación y ejecución independientes es útil en un entorno como Kubernetes. En Kubernetes, es posible que una aplicación deba realizar un trabajo de inicio que requiera mucho tiempo antes de aceptar solicitudes, como una prueba de la disponibilidad de la base de datos subyacente. El hecho de utilizar comprobaciones independientes permite que el orquestador distinga si la aplicación está funcionando, pero aún no esté preparada, o si la aplicación no se ha podido iniciar. Para obtener más información sobre los sondeos de preparación y ejecución en Kubernetes, consulte Configuración de sondeos de preparación y ejecución en la documentación de Kubernetes.
En el ejemplo siguiente, se muestra una configuración de sondeo de preparación de 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
Sondeo basado en métrica con un escritor de respuesta personalizada
La aplicación de ejemplo muestra una comprobación de estado de memoria con un escritor de respuesta personalizada.
MemoryHealthCheck notifica un estado degradado si la aplicación usa más de un umbral de memoria determinado (1 GB en la aplicación de ejemplo). El elemento HealthCheckResult incluye información del recolector de elementos no utilizados (GC) de la aplicación (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));
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. En lugar de pasar la comprobación de estado a AddCheck para habilitarla, MemoryHealthCheck se registra como servicio. Todos los servicios registrados de IHealthCheck están disponibles para los servicios de comprobación de estado y middleware. Se recomienda registrar los servicios de comprobación de estado como los servicios de Singleton.
En CustomWriterStartup.cs de la aplicación de ejemplo:
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
Se crea un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure. Se proporciona un delegado WriteResponse a la propiedad <Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions.ResponseWriter> para generar una respuesta JSON personalizada cuando se ejecuta la comprobación de estado:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
}
El delegado WriteResponse da a CompositeHealthCheckResult el formato de objeto JSON y suspende el resultado de JSON para la respuesta de comprobación de estado. Para más información, consulte la sección Personalización del resultado.
Para ejecutar el sondeo basado en métrica con el resultado de un escritor de respuesta personalizada mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario writer
Nota
AspNetCore.Diagnostics.HealthChecks incluye escenarios de comprobación de estado basados en métricas, como las comprobaciones del almacenamiento del disco y de ejecución de máximo valor.
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Filtrado por puerto
Llame a RequireHost en MapHealthChecks con un patrón de dirección URL que especifique un puerto para restringir las solicitudes de comprobación de estado al puerto especificado. Esto se usa normalmente en un entorno de contenedor para exponer un puerto para los servicios de supervisión.
La aplicación de ejemplo configura el puerto con el proveedor de configuración de variable de entorno. El puerto se establece en el archivo launchSettings.json y se pasa al proveedor de configuración a través de una variable de entorno. También debe configurar el servidor para que escuche las solicitudes en el puerto de administración.
Para utilizar la aplicación de ejemplo para que muestre la configuración del puerto de administración, cree el archivo launchSettings.json en una carpeta Properties.
El archivo Properties/launchSettings.json siguiente de la aplicación de ejemplo no se incluye en los archivos de proyecto de la aplicación de ejemplo y se debe crear manualmente:
{
"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/"
}
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. Cree un punto de conexión de comprobación de estado llamando a MapHealthChecks en Startup.Configure.
En la aplicación de ejemplo, una llamada a RequireHost en el punto de conexión Startup.Configure especifica el puerto de administración de la configuración:
endpoints.MapHealthChecks("/health")
.RequireHost($"*:{Configuration["ManagementPort"]}");
Los puntos de conexión se crean en la aplicación de ejemplo en Startup.Configure. En el código de ejemplo siguiente:
- La comprobación de preparación usa todas las comprobaciones registradas con la etiqueta "ready".
Predicateexcluye todas las comprobaciones y devuelve una respuesta de que todo está correcto (200-OK).
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Nota
Para evitar la creación del archivo launchSettings.json en la aplicación de ejemplo, configure el puerto de administración explícitamente en código. En Program.cs, donde se crea HostBuilder, agregue una llamada a ListenAnyIP y proporcione el punto de conexión del puerto de administración de la aplicación. En Configure de ManagementPortStartup.cs, especifique el puerto de administración con RequireHost:
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");
});
Para ejecutar el escenario de configuración del puerto de administración mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario port
Distribución de una biblioteca de comprobación de estado
Para distribuir una comprobación de estado como una biblioteca, haga lo siguiente:
Escriba una comprobación de estado que implemente la interfaz de IHealthCheck como una clase independiente. La clase puede depender de la inserción de dependencias (DI), de la activación del tipo y de las opciones denominadas para acceder a los datos de configuración.
En la lógica de comprobaciones de estado de
CheckHealthAsync:data1ydata2se usan en el método para ejecutar la lógica de comprobación de estado del sondeo.- Se controla
AccessViolationException.
Cuando se produce un AccessViolationException, se devuelve FailureStatus con HealthCheckResult para permitir que los usuarios configuren el estado de error de las comprobaciones de estado.
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); } } } }Escriba un método de extensión con los parámetros a los que la aplicación de uso llama en su método
Startup.Configure. En el ejemplo siguiente, suponga que existe la siguiente firma del método de comprobación de estado:ExampleHealthCheck(string, string, int )La firma anterior indica que la
ExampleHealthCheckrequiere datos adicionales para procesar la lógica de sondeo de la comprobación de estado. Los datos se proporcionan al delegado que se usa para crear la instancia de la comprobación de estado cuando la comprobación de estado se registra con un método de extensión. En el ejemplo siguiente, el autor de llamada especifica los siguientes elementos opcionales:- nombre de la comprobación de estado (
name). En el caso denull, se utilizaexample_health_check. - punto de datos de cadena para la comprobación de estado (
data1). - punto de datos enteros para la comprobación de estado (
data2). En el caso denull, se utiliza1. - estado de error (HealthStatus). De manera predeterminada, es
null. Si esnull, se notificaHealthStatus.Unhealthypara un estado de error. - etiquetas (
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)); } }- nombre de la comprobación de estado (
Publicador de la comprobación de estado
Cuando un elemento IHealthCheckPublisher se agrega al contenedor de servicios, el sistema de comprobación de estado ejecuta periódicamente las comprobaciones de estado y llama a PublishAsync con el resultado. Esto es útil en un escenario de sistema de seguimiento de estado basado en inserción en el que se espera que cada proceso llame periódicamente al sistema de seguimiento con el fin de determinar el estado.
La interfaz de IHealthCheckPublisher tiene un único método:
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions le permiten establecer:
- Delay: el retraso inicial aplicado tras iniciarse la aplicación antes de ejecutar instancias de IHealthCheckPublisher. El retraso se aplica una vez durante el inicio y no se aplica a las iteraciones posteriores. El valor predeterminado es cinco segundos.
- Period: el período de ejecución de IHealthCheckPublisher. El valor predeterminado es 30 segundos.
- Predicate: si Predicate es
null(valor predeterminado), el servicio de publicador de la comprobación de estado ejecuta todas las comprobaciones de estado registradas. Para ejecutar un subconjunto de comprobaciones de estado, proporcione una función que filtre el conjunto de comprobaciones. El predicado se evalúa cada período. - Timeout: el tiempo de expiración para ejecutar las comprobaciones de estado para todas las instancias de IHealthCheckPublisher. Use InfiniteTimeSpan para ejecutar sin tiempo de expiración. El valor predeterminado es 30 segundos.
En la aplicación de ejemplo, ReadinessPublisher es una implementación de IHealthCheckPublisher. El estado de comprobación de estado se registra para cada comprobación en un nivel de registro de:
- Información (LogInformation) si el estado de las comprobaciones de estado es Healthy.
- Error (LogError) si el estado es Degraded o Unhealthy.
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;
}
}
En el ejemplo LivenessProbeStartup de la aplicación de ejemplo, la comprobación de preparación StartupHostedService tiene un retraso de inicio de dos segundos y ejecuta la comprobación cada 30 segundos. Para activar la implementación de IHealthCheckPublisher, el ejemplo registra ReadinessPublisher como servicio singleton en el contenedor de inserción de dependencias (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>();
Nota
AspNetCore.Diagnostics.HealthChecks incluye editores para varios sistemas, incluido Application Insights.
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Restricción de las comprobaciones de estado con MapWhen
Use MapWhen para crear de forma condicional una rama de la canalización de solicitudes para los puntos de conexión de comprobación del estado.
En el ejemplo siguiente, MapWhen crea una rama de la canalización de solicitudes para activar el middleware de comprobaciones de estado si se recibe una solicitud GET para el punto de conexión api/HealthCheck:
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
Para obtener más información, vea Middleware de ASP.NET Core.
ASP.NET Core ofrece el middleware de comprobaciones de estado y bibliotecas para informar sobre el estado de los componentes de la infraestructura de la aplicación.
Una aplicación se encarga de exponer las comprobaciones de estado como puntos de conexión HTTP. Los puntos de conexión de las comprobaciones de estado pueden configurarse para diversos escenarios de supervisión en tiempo real:
- Los orquestadores de contenedores y los equilibradores de carga pueden utilizar los sondeos de estado para comprobar el estado de una aplicación. Por ejemplo, para responder a una comprobación de estado con errores, es posible que un orquestador de contenedores detenga una implementación en curso o reinicie un contenedor. Como respuesta a una aplicación con estado incorrecto, es posible que un equilibrador de carga enrute el tráfico al margen de la instancia con errores hacia una instancia con estado correcto.
- El uso de la memoria, el disco y otros recursos del servidor físico puede supervisarse para determinar si el estado es correcto.
- Las comprobaciones de estado pueden probar las dependencias de una aplicación, como las bases de datos y los puntos de conexión de servicio externo, para confirmar la disponibilidad y el funcionamiento normal.
Vea o descargue el código de ejemplo (cómo descargarlo)
La aplicación de muestra incluye ejemplos de los escenarios descritos en este tema. Para ejecutar la aplicación de ejemplo para un escenario determinado, use el comando dotnet run desde la carpeta del proyecto en un shell de comandos. Para obtener información sobre cómo utilizar la aplicación de ejemplo, consulte el archivo README.md de la aplicación de ejemplo y las descripciones de escenarios de este tema.
Requisitos previos
Normalmente, las comprobaciones de estado se usan con un servicio de supervisión externa o un orquestador de contenedores para comprobar el estado de una aplicación. Antes de agregar comprobaciones de estado a una aplicación, debe decidir en qué sistema de supervisión se va a usar. El sistema de supervisión determina qué tipos de comprobaciones de estado se deben crear y cómo configurar sus puntos de conexión.
Haga referencia al metapaquete Microsoft.AspNetCore.App o agregue una referencia al paquete Microsoft.AspNetCore.Diagnostics.HealthChecks.
La aplicación de ejemplo proporciona código de inicio para mostrar las comprobaciones de estado para varios escenarios. En el escenario sondeo de base de datos se comprueba el estado de una conexión de base de datos mediante AspNetCore.Diagnostics.HealthChecks. El escenario sondeo de DbContext comprueba una base de datos mediante un elemento DbContext de EF Core. Para explorar los escenarios de la base de datos, la aplicación de ejemplo:
- Crea una base de datos y proporciona su cadena de conexión en el archivo appsettings.json .
- Tiene las siguientes referencias de paquete en su archivo de proyecto:
Nota
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Otro escenario de comprobación de estado muestra cómo filtrar las comprobaciones de estado por un puerto de administración. La aplicación de ejemplo requiere la creación de un archivo Properties/launchSettings.json que incluya la dirección URL de administración y el puerto de administración. Para obtener más información, consulte la sección Filtrado por puerto.
Sondeo de estado básico
Para muchas aplicaciones, una configuración de sondeo de estado básico que notifique la disponibilidad de la aplicación para procesar las solicitudes (ejecución) es suficiente para detectar el estado de la aplicación.
La configuración básica registra los servicios de comprobación de estado y llama al middleware de comprobaciones de estado para responder a un punto de conexión de dirección URL con una respuesta de estado. De forma predeterminada, no se registran comprobaciones de estado específicas para probar cualquier dependencia o subsistema concretos. La aplicación se considera correcta si es capaz de responder en la dirección URL de punto de conexión de estado. El escritor de respuesta predeterminado escribe el estado (HealthStatus) como respuesta de texto no cifrado en el cliente, que indica un estado HealthStatus.Healthy, HealthStatus.Degraded o HealthStatus.Unhealthy.
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. Agregue un punto de conexión para el middleware de comprobaciones de estado con UseHealthChecks en la canalización de procesamiento de solicitudes de Startup.Configure.
En la aplicación de ejemplo, el punto de conexión de la comprobación de estado se crea en /health (BasicStartup.cs):
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/health");
}
}
Para ejecutar el escenario de configuración básica mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario basic
Ejemplo de Docker
Docker ofrece una directiva de HEALTHCHECK integrada que puede utilizarse para comprobar el estado de una aplicación que use la configuración de comprobación de estado básica:
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
Creación de comprobaciones de estado
Las comprobaciones de estado se crean mediante la implementación de la interfaz de IHealthCheck. El método CheckHealthAsync devuelve un elemento HealthCheckResult que indica el estado como Healthy, Degraded o Unhealthy. El resultado se escribe como una respuesta de texto no cifrado con un código de estado configurable. (La configuración se describe en la sección Opciones de comprobación de estado). HealthCheckResult también puede devolver pares clave-valor opcionales.
Comprobación de estado de ejemplo
La siguiente clase ExampleHealthCheck muestra el diseño de una comprobación de estado. La lógica de comprobaciones de estado se coloca en el método CheckHealthAsync. En el ejemplo siguiente se establece una variable ficticia, healthCheckResultHealthy, en true. Si el valor de healthCheckResultHealthy se establece en false, se devuelve el estado HealthCheckResult.Unhealthy.
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("The check indicates a healthy result."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("The check indicates an unhealthy result."));
}
}
Registro de los servicios de comprobación de estado
El tipo ExampleHealthCheck se agrega a los servicios de comprobación de estado en Startup.ConfigureServices con AddCheck:
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
La sobrecarga AddCheck que se muestra en el ejemplo siguiente establece el estado de error (HealthStatus) para notificar cuándo la comprobación de estado informa de un error. Si el estado de error se establece en null (valor predeterminado), se notifica HealthStatus.Unhealthy. Esta sobrecarga es un escenario útil para los creadores de bibliotecas en los que la aplicación ejecuta el estado de error indicado por la biblioteca cuando se produce un error de comprobación de estado si la implementación de la comprobación de estado respeta la configuración.
Las etiquetas pueden usarse para filtrar las comprobaciones de estado, que se describen con más detalle en la sección Filtrado de las comprobaciones de estado.
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck también puede ejecutar una función lambda. En el ejemplo siguiente Startup.ConfigureServices, el nombre de la comprobación de estado se especifica como Example y la comprobación siempre devuelve un estado correcto:
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
Uso del Middleware de comprobaciones de estado
En Startup.Configure, llame a UseHealthChecks en la canalización de procesamiento con la dirección URL del punto de conexión o la ruta de acceso relativa:
app.UseHealthChecks("/health");
Si las comprobaciones de estado deben realizar la escucha en un puerto específico, use una sobrecarga de UseHealthChecks para establecer el puerto, como se describe con más detalle en la sección Filtrado por puerto:
app.UseHealthChecks("/health", port: 8000);
Opciones de comprobación de estado
El elemento HealthCheckOptions ofrece una oportunidad para personalizar el comportamiento de las comprobaciones de estado:
- Filtrado de las comprobaciones de estado
- Personalización del código de estado HTTP
- Supresión de los encabezados de caché
- Personalización del resultado
Filtrado de las comprobaciones de estado
De forma predeterminada, el middleware de comprobaciones de estado ejecuta todas las comprobaciones de estado registradas. Para ejecutar un subconjunto de comprobaciones de estado, proporcione una función que devuelva un valor booleano para la opción Predicate. En el ejemplo siguiente, la etiqueta (bar_tag) de la comprobación de estado Bar la filtra, en la instrucción condicional de la función, donde true solo se devuelve si la propiedad Tags de la comprobación de estado coincide con foo_tag o baz_tag:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
public void ConfigureServices(IServiceCollection services)
{
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" });
}
public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
}
Personalización del código de estado HTTP
Use ResultStatusCodes para personalizar la asignación del estado de mantenimiento de los códigos de estado HTTP. Las siguientes asignaciones de StatusCodes son los valores predeterminados que el middleware utiliza. Cambie los valores de código de estado para satisfacer sus necesidades.
En Startup.Configure:
//using Microsoft.AspNetCore.Diagnostics.HealthChecks;
//using Microsoft.Extensions.Diagnostics.HealthChecks;
app.UseHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
Supresión de los encabezados de caché
AllowCachingResponses controla si el middleware de comprobaciones de estado agrega encabezados HTTP a una respuesta de sondeo para evitar el almacenamiento en caché de respuesta. Si el valor es false (valor predeterminado), el middleware establece o invalida los encabezados Cache-Control, Expires y Pragma para evitar el almacenamiento en caché de respuesta. Si el valor es true, el middleware no modifica los encabezados de caché de la respuesta.
En Startup.Configure:
//using Microsoft.AspNetCore.Diagnostics.HealthChecks;
//using Microsoft.Extensions.Diagnostics.HealthChecks;
app.UseHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = false
});
Personalización del resultado
La opción ResponseWriter obtiene o establece un delegado que se usa para escribir la respuesta. El delegado predeterminado escribe una respuesta de texto no cifrado mínima con el valor de cadena HealthReport.Status.
En Startup.Configure:
// using Microsoft.AspNetCore.Diagnostics.HealthChecks;
// using Microsoft.Extensions.Diagnostics.HealthChecks;
app.UseHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
El delegado predeterminado escribe una respuesta de texto no cifrado mínima con el valor de cadena HealthReport.Status. El siguiente delegado personalizado, WriteResponse, genera una respuesta JSON personalizada:
private static Task WriteResponse(HttpContext httpContext, HealthReport result)
{
httpContext.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 httpContext.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
El sistema de comprobaciones de estado no ofrece compatibilidad integrada con formatos de retorno JSON complejos porque el formato es específico del sistema de supervisión elegido. No dude en personalizar JObject en el ejemplo anterior según sea sus necesidades.
Sondeo de bases de datos
Una comprobación de estado puede especificar que una consulta de base de datos se ejecute como una prueba booleana para indicar si esta responde con normalidad.
En la aplicación de ejemplo se usa AspNetCore.Diagnostics.HealthChecks, una biblioteca de comprobaciones de estado para las aplicaciones de ASP.NET Core, a fin de realizar una comprobación de estado en una base de datos de SQL Server. AspNetCore.Diagnostics.HealthChecks ejecuta una consulta SELECT 1 en la base de datos para confirmar que la conexión a la base de datos es correcta.
Advertencia
Al comprobar la conexión de una base de datos a una consulta, elija una consulta que se devuelva rápidamente. El enfoque de la consulta plantea el riesgo de sobrecargar la base de datos y degradar el rendimiento. En la mayoría de los casos, no es necesario ejecutar una consulta de prueba. Simplemente, realizar una conexión correcta a la base de datos es suficiente. Si resulta necesario ejecutar una consulta, elija una consulta SELECT sencilla, como SELECT 1.
Incluya una referencia de paquete a AspNetCore.HealthChecks.SqlServer.
Proporcione una cadena de conexión a base de datos válida en el archivo appsettings.json de la aplicación de ejemplo. La aplicación usa una base de datos de SQL Server denominada HealthCheckSample:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
},
"Logging": {
"LogLevel": {
"Default": "Debug"
},
"Console": {
"IncludeScopes": "true"
}
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. La aplicación de ejemplo llama al método AddSqlServer con la cadena de conexión de la base de datos (DbHealthStartup.cs):
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
}
Llame al middleware de comprobaciones de estado en la canalización de procesamiento de la aplicación en Startup.Configure:
app.UseHealthChecks("/health");
Para ejecutar el escenario de sondeo de base de datos mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario db
Nota
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Sondeo de DbContext de Entity Framework Core
La comprobación DbContext confirma que la aplicación puede comunicarse con la base de datos configurada para un elemento DbContext de EF Core. La comprobación DbContext se admite en las aplicaciones que:
- Usan Entity Framework (EF) Core.
- Incluya una referencia de paquete a
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.
AddDbContextCheck<TContext> registra una comprobación de estado para un elemento DbContext. El elemento DbContext se proporciona como TContext en el método. Hay disponible una sobrecarga para configurar el estado de error, las etiquetas y una consulta de prueba personalizada.
De manera predeterminada:
DbContextHealthCheckllama al métodoCanConnectAsyncde EF Core. Se puede personalizar qué operación se ejecuta al comprobar el estado con sobrecargas del métodoAddDbContextCheck.- El nombre de la comprobación de estado es el nombre del tipo
TContext.
En la aplicación de ejemplo, AppDbContext se proporciona para AddDbContextCheck y se registra como un servicio en Startup.ConfigureServices (DbContextHealthStartup.cs):
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
}
En la aplicación de ejemplo, UseHealthChecks agrega el middleware de comprobaciones de estado en Startup.Configure.
app.UseHealthChecks("/health");
Para ejecutar el escenario de sondeo de DbContext mediante la aplicación de ejemplo, confirme que la base de datos que la cadena de conexión especifica no exista en la instancia de SQL Server. Si la base de datos existe, elimínela.
Ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario dbcontext
Cuando la aplicación ya se esté ejecutando, compruebe el estado de mantenimiento mediante una solicitud al punto de conexión /health en un explorador. La base de datos y AppDbContext no existen, por lo que la aplicación proporciona la respuesta siguiente:
Unhealthy
Active la aplicación de ejemplo para crear la base de datos. Realice una solicitud a /createdatabase. La aplicación responde:
Creating the database...
Done!
Navigate to /health to see the health status.
Realice una solicitud al punto de conexión /health. La base de datos y el contexto existen, por lo que la aplicación responde:
Healthy
Active la aplicación de ejemplo para eliminar la base de datos. Realice una solicitud a /deletedatabase. La aplicación responde:
Deleting the database...
Done!
Navigate to /health to see the health status.
Realice una solicitud al punto de conexión /health. La aplicación proporciona una respuesta incorrecta:
Unhealthy
Sondeos de preparación y ejecución independientes
En algunos escenarios de hospedaje, se usa un par de comprobaciones de estado que distinguen los dos estados de la aplicación:
- Preparación indica si la aplicación se ejecuta con normalidad, pero no está lista para recibir solicitudes.
- Ejecución indica si una aplicación se ha bloqueado y debe reiniciarse.
Considere el ejemplo siguiente: Antes de estar lista para procesar solicitudes, una aplicación debe descargar un archivo de configuración de gran tamaño. No queremos que se reinicie la aplicación si se produce un error en la descarga inicial, dado que la aplicación puede volver a intentar descargar el archivo varias veces. Usamos un sondeo de ejecución para describir la ejecución del proceso, sin realizar ninguna otra comprobación. También queremos evitar que las solicitudes se envíen a la aplicación antes de que finalice la descarga del archivo de configuración. Hasta que no finaliza la descarga y la aplicación está lista para recibir solicitudes, usamos un sondeo de preparación para indicar un estado "no preparado".
La aplicación de ejemplo contiene una comprobación de estado para notificar la finalización de la tarea de inicio de ejecución prolongada en un servicio hospedado. El elemento StartupHostedServiceHealthCheck expone una propiedad, StartupTaskCompleted, que el servicio hospedado puede establecer en true al terminar su tarea de ejecución prolongada (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."));
}
}
Un servicio hospedado (Services/StartupHostedService) se encarga de iniciar la tarea en segundo plano de larga ejecución. Al finalizar la tarea, StartupHostedServiceHealthCheck.StartupTaskCompleted se establece en true:
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()
{
}
}
La comprobación de estado se registra con AddCheck en Startup.ConfigureServices junto con el servicio hospedado. Dado que el servicio hospedado debe establecer la propiedad en la comprobación de estado, esta también se registra en el contenedor de servicios (LivenessProbeStartup.cs):
public void ConfigureServices(IServiceCollection services)
{
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");
});
// The following workaround permits adding an IHealthCheckPublisher
// instance to the service container when one or more other hosted
// services have already been added to the app. This workaround
// won't be required with the release of ASP.NET Core 3.0. For more
// information, see: https://github.com/aspnet/Extensions/issues/639.
services.TryAddEnumerable(
ServiceDescriptor.Singleton(typeof(IHostedService),
typeof(HealthCheckPublisherOptions).Assembly
.GetType(HealthCheckServiceAssembly)));
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
}
Llame al middleware de comprobaciones de estado en la canalización de procesamiento de la aplicación en Startup.Configure. En la aplicación de ejemplo, se crean puntos de conexión de la comprobación de estado en /health/ready para la comprobación de preparación y en /health/live para la comprobación de ejecución. La comprobación de preparación filtra las comprobaciones de estado con la etiqueta ready. La comprobación de ejecución filtra el elemento StartupHostedServiceHealthCheck mediante la devolución de false en HealthCheckOptions.Predicate (para obtener más información, vea Filtrado de las comprobaciones de estado):
app.UseHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
app.UseHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
Para ejecutar el escenario de configuración de la preparación/ejecución mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario liveness
En un explorador, visite /health/ready varias veces hasta que hayan pasado 15 segundos. La comprobación de estado notifica un estado Incorrecto durante los primeros 15 segundos. Pasados 15 segundos, el punto de conexión notifica un estado Correcto, lo que indica que el servicio hospedado ya ha finalizado la tarea de ejecución prolongada.
En este ejemplo también se crea un publicador de la comprobación de estado (IHealthCheckPublisher implementación) que ejecuta la primera comprobación de preparación con un retraso de dos segundos. Para obtener más información, consulte la sección Publicador de la comprobación de estado.
Ejemplo de Kubernetes
Utilizar comprobaciones de preparación y ejecución independientes es útil en un entorno como Kubernetes. En Kubernetes, es posible que una aplicación deba realizar un trabajo de inicio que requiera mucho tiempo antes de aceptar solicitudes, como una prueba de la disponibilidad de la base de datos subyacente. El hecho de utilizar comprobaciones independientes permite que el orquestador distinga si la aplicación está funcionando, pero aún no esté preparada, o si la aplicación no se ha podido iniciar. Para obtener más información sobre los sondeos de preparación y ejecución en Kubernetes, consulte Configuración de sondeos de preparación y ejecución en la documentación de Kubernetes.
En el ejemplo siguiente, se muestra una configuración de sondeo de preparación de 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
Sondeo basado en métrica con un escritor de respuesta personalizada
La aplicación de ejemplo muestra una comprobación de estado de memoria con un escritor de respuesta personalizada.
MemoryHealthCheck notifica un estado incorrecto si la aplicación usa más de un umbral de memoria determinado (1 GB en la aplicación de ejemplo). El elemento HealthCheckResult incluye información del recolector de elementos no utilizados (GC) de la aplicación (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 : HealthStatus.Unhealthy;
return Task.FromResult(new HealthCheckResult(
status,
description: "Reports degraded status if allocated bytes " +
$">= {options.Threshold} bytes.",
exception: null,
data: data));
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. En lugar de pasar la comprobación de estado a AddCheck para habilitarla, MemoryHealthCheck se registra como servicio. Todos los servicios registrados de IHealthCheck están disponibles para los servicios de comprobación de estado y middleware. Se recomienda registrar los servicios de comprobación de estado como los servicios de Singleton.
En la aplicación de ejemplo (CustomWriterStartup.cs):
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
}
Llame al middleware de comprobaciones de estado en la canalización de procesamiento de la aplicación en Startup.Configure. Se proporciona un delegado de WriteResponse a la propiedad ResponseWriter para generar una respuesta JSON personalizada al ejecutarse la comprobación de estado:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/health", new HealthCheckOptions()
{
// This custom writer formats the detailed status as JSON.
ResponseWriter = WriteResponse
});
}
El método WriteResponse da a CompositeHealthCheckResult el formato de objeto JSON y suspende el resultado de JSON para la respuesta de comprobación de estado:
private static Task WriteResponse(HttpContext httpContext,
HealthReport result)
{
httpContext.Response.ContentType = "application/json; charset=utf-8";
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 httpContext.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
Para ejecutar el sondeo basado en métrica con el resultado de un escritor de respuesta personalizada mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario writer
Nota
AspNetCore.Diagnostics.HealthChecks incluye escenarios de comprobación de estado basados en métricas, como las comprobaciones del almacenamiento del disco y de ejecución de máximo valor.
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Filtrado por puerto
Una llamada a UseHealthChecks con un puerto restringe las solicitudes de comprobación de estado al puerto especificado. Esto se usa normalmente en un entorno de contenedor para exponer un puerto para los servicios de supervisión.
La aplicación de ejemplo configura el puerto con el proveedor de configuración de variable de entorno. El puerto se establece en el archivo launchSettings.json y se pasa al proveedor de configuración a través de una variable de entorno. También debe configurar el servidor para que escuche las solicitudes en el puerto de administración.
Para utilizar la aplicación de ejemplo para que muestre la configuración del puerto de administración, cree el archivo launchSettings.json en una carpeta Propiedades.
El siguiente archivo Properties/launchSettings.json de la aplicación de ejemplo no se incluye en los archivos de proyecto de la aplicación de ejemplo y debe crearse manualmente:
{
"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/"
}
}
}
Registre los servicios de comprobación de estado con AddHealthChecks de Startup.ConfigureServices. La llamada a UseHealthChecks especifica el puerto de administración (ManagementPortStartup.cs):
public class ManagementPortStartup
{
public ManagementPortStartup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/health", port: Configuration["ManagementPort"]);
app.Run(async (context) =>
{
await context.Response.WriteAsync(
"Navigate to " +
$"http://localhost:{Configuration["ManagementPort"]}/health " +
"to see the health status.");
});
}
}
Nota
Para evitar la creación del archivo launchSettings.json en la aplicación de ejemplo, configure las direcciones URL y el puerto de administración explícitamente en código. En Program.cs, donde se crea WebHostBuilder, agregue una llamada a UseUrls y proporcione el punto de conexión de respuesta normal de la aplicación y el punto de conexión del puerto de administración. En ManagementPortStartup.cs, donde se llama a UseHealthChecks, especifique explícitamente el puerto de administración.
Program.cs:
return new WebHostBuilder()
.UseConfiguration(config)
.UseUrls("http://localhost:5000/;http://localhost:5001/")
.ConfigureLogging(builder =>
{
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConfiguration(config);
builder.AddConsole();
})
.UseKestrel()
.UseStartup(startupType)
.Build();
ManagementPortStartup.cs:
app.UseHealthChecks("/health", port: 5001);
Para ejecutar el escenario de configuración del puerto de administración mediante la aplicación de ejemplo, ejecute el comando siguiente desde la carpeta del proyecto en un shell de comandos:
dotnet run --scenario port
Distribución de una biblioteca de comprobación de estado
Para distribuir una comprobación de estado como una biblioteca, haga lo siguiente:
Escriba una comprobación de estado que implemente la interfaz de IHealthCheck como una clase independiente. La clase puede depender de la inserción de dependencias (DI), de la activación del tipo y de las opciones denominadas para acceder a los datos de configuración.
En la lógica de comprobaciones de estado de
CheckHealthAsync:data1ydata2se usan en el método para ejecutar la lógica de comprobación de estado del sondeo.- Se controla
AccessViolationException.
Cuando se produce un AccessViolationException, se devuelve FailureStatus con HealthCheckResult para permitir que los usuarios configuren el estado de error de las comprobaciones de estado.
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Diagnostics.HealthChecks; 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); } } }Escriba un método de extensión con los parámetros a los que la aplicación de uso llama en su método
Startup.Configure. En el ejemplo siguiente, suponga que existe la siguiente firma del método de comprobación de estado:ExampleHealthCheck(string, string, int )La firma anterior indica que la
ExampleHealthCheckrequiere datos adicionales para procesar la lógica de sondeo de la comprobación de estado. Los datos se proporcionan al delegado que se usa para crear la instancia de la comprobación de estado cuando la comprobación de estado se registra con un método de extensión. En el ejemplo siguiente, el autor de llamada especifica los siguientes elementos opcionales:- nombre de la comprobación de estado (
name). En el caso denull, se utilizaexample_health_check. - punto de datos de cadena para la comprobación de estado (
data1). - punto de datos enteros para la comprobación de estado (
data2). En el caso denull, se utiliza1. - estado de error (HealthStatus). De manera predeterminada, es
null. Si esnull, se notificaHealthStatus.Unhealthypara un estado de error. - etiquetas (
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)); } }- nombre de la comprobación de estado (
Publicador de la comprobación de estado
Cuando un elemento IHealthCheckPublisher se agrega al contenedor de servicios, el sistema de comprobación de estado ejecuta periódicamente las comprobaciones de estado y llama a PublishAsync con el resultado. Esto es útil en un escenario de sistema de seguimiento de estado basado en inserción en el que se espera que cada proceso llame periódicamente al sistema de seguimiento con el fin de determinar el estado.
La interfaz de IHealthCheckPublisher tiene un único método:
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions le permiten establecer:
- Delay: el retraso inicial aplicado tras iniciarse la aplicación antes de ejecutar instancias de IHealthCheckPublisher. El retraso se aplica una vez durante el inicio y no se aplica a las iteraciones posteriores. El valor predeterminado es cinco segundos.
- Period: el período de ejecución de IHealthCheckPublisher. El valor predeterminado es 30 segundos.
- Predicate: si Predicate es
null(valor predeterminado), el servicio de publicador de la comprobación de estado ejecuta todas las comprobaciones de estado registradas. Para ejecutar un subconjunto de comprobaciones de estado, proporcione una función que filtre el conjunto de comprobaciones. El predicado se evalúa cada período. - Timeout: el tiempo de expiración para ejecutar las comprobaciones de estado para todas las instancias de IHealthCheckPublisher. Use InfiniteTimeSpan para ejecutar sin tiempo de expiración. El valor predeterminado es 30 segundos.
Advertencia
En la versión de ASP.NET Core 2.2, el establecimiento de Period no se asigna por medio de la implementación de IHealthCheckPublisher; establece el valor de Delay. Este problema se ha corregido en ASP.NET Core 3.0.
En la aplicación de ejemplo, ReadinessPublisher es una implementación de IHealthCheckPublisher. El estado de comprobación de estado se registra para cada comprobación como:
- Información (LogInformation) si el estado de las comprobaciones de estado es Healthy.
- Error (LogError) si el estado es Degraded o Unhealthy.
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;
}
}
En el ejemplo LivenessProbeStartup de la aplicación de ejemplo, la comprobación de preparación StartupHostedService tiene un retraso de inicio de dos segundos y ejecuta la comprobación cada 30 segundos. Para activar la implementación de IHealthCheckPublisher, el ejemplo registra ReadinessPublisher como servicio singleton en el contenedor de inserción de dependencias (DI):
public void ConfigureServices(IServiceCollection services)
{
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");
});
// The following workaround permits adding an IHealthCheckPublisher
// instance to the service container when one or more other hosted
// services have already been added to the app. This workaround
// won't be required with the release of ASP.NET Core 3.0. For more
// information, see: https://github.com/aspnet/Extensions/issues/639.
services.TryAddEnumerable(
ServiceDescriptor.Singleton(typeof(IHostedService),
typeof(HealthCheckPublisherOptions).Assembly
.GetType(HealthCheckServiceAssembly)));
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
}
Nota
La siguiente solución alternativa permite la adición de una instancia de IHealthCheckPublisher al contenedor del servicio cuando uno o más servicios hospedados ya se han agregado a la aplicación. Esta solución no es necesaria en ASP.NET Core 3.0.
private const string HealthCheckServiceAssembly =
"Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckPublisherHostedService";
services.TryAddEnumerable(
ServiceDescriptor.Singleton(typeof(IHostedService),
typeof(HealthCheckPublisherOptions).Assembly
.GetType(HealthCheckServiceAssembly)));
Nota
AspNetCore.Diagnostics.HealthChecks incluye editores para varios sistemas, incluido Application Insights.
Microsoft no mantiene ni admite AspNetCore.Diagnostics.HealthChecks.
Restricción de las comprobaciones de estado con MapWhen
Use MapWhen para crear de forma condicional una rama de la canalización de solicitudes para los puntos de conexión de comprobación del estado.
En el ejemplo siguiente, MapWhen crea una rama de la canalización de solicitudes para activar el middleware de comprobaciones de estado si se recibe una solicitud GET para el punto de conexión api/HealthCheck:
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseMvc();
Para obtener más información, vea Middleware de ASP.NET Core.