Skip to content

在ASP.NET Core中使用健康检查监控您的应用程序

Published: at 12:00 AM

在ASP.NET Core中使用健康检查监控您的应用程序

摘要

原文 Health Checks In ASP.NET Core For Monitoring Your ApplicationsMilan Jovanović 发表。


我们都希望构建健壮可靠的应用程序,这些应用程序能无限扩展并处理任意数量的请求。

但随着分布式系统微服务架构增长的复杂性,监控我们应用程序的健康变得越来越困难。

拥有一个系统来快速反馈应用程序健康状态是至关重要的。

这就是健康检查的用武之地。

健康检查提供了一种监控和验证应用程序各个组件健康情况的方法,包括:

让我们看看如何在ASP.NET Core中实现健康检查

什么是健康检查?

健康检查是一种主动机制,用于监控和验证ASP.NET Core中应用程序的健康状态可用性

ASP.NET Core具有内置支持来实现健康检查

这是基本配置,它注册健康检查服务,并添加HealthCheckMiddleware以在指定的URL响应。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/health");

app.Run();

健康检查返回一个HealthStatus值,指示服务的健康状态。

有三种不同的HealthStatus值:

您可以使用HealthStatus来指示应用程序的不同状态。

例如,如果应用程序的运行速度比预期慢,你可以返回HealthStatus.Degraded

添加自定义健康检查

您可以通过实现IHealthCheck接口来创建自定义健康检查

例如,您可以实现一个检查,看看您的SQL数据库是否可用。

在数据库中使用一个能快速完成的查询是很重要的,比如SELECT 1

这是在SqlHealthCheck类中的一个自定义健康检查实现示例:

public class SqlHealthCheck : IHealthCheck
{
    private readonly string _connectionString;

    public SqlHealthCheck(IConfiguration configuration)
    {
        _connectionString = configuration.GetConnectionString("Database");
    }

    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            using var sqlConnection = new SqlConnection(_connectionString);

            await sqlConnection.OpenAsync(cancellationToken);

            using var command = sqlConnection.CreateCommand();
            command.CommandText = "SELECT 1";

            await command.ExecuteScalarAsync(cancellationToken);

            return HealthCheckResult.Healthy();
        }
        catch(Exception ex)
        {
            return HealthCheckResult.Unhealthy(
                context.Registration.FailureStatus,
                exception: ex);
        }
    }
}

实现自定义健康检查后,您需要进行注册。

之前对AddHealthChecks的调用现在变为:

builder.Services.AddHealthChecks()
    .AddCheck<SqlHealthCheck>("custom-sql", HealthStatus.Unhealthy);

我们给它一个自定义名称,并设置在HealthCheckContext.Registration.FailureStatus中使用哪种状态作为失败结果。

但是,请稍停一下思考。

对于你拥有的每一个外部服务,你都想自己实现一个自定义健康检查吗?

当然不是!有一个更好的解决方案。

使用现有健康检查库

在你开始为每件事实现自定义健康检查之前,你应该首先看看是否已经有了一个现有的库

AspNetCore.Diagnostics.HealthChecks仓库中,你可以找到用于常用服务和库的广泛集合健康检查包。

这里有一些示例:

以下是如何为PostgreSQLRabbitMQ添加健康检查:

builder.Services.AddHealthChecks()
    .AddCheck<SqlHealthCheck>("custom-sql", HealthStatus.Unhealthy);
    .AddNpgSql(pgConnectionString)
    .AddRabbitMQ(rabbitConnectionString)

格式化健康检查响应

默认情况下,返回你的健康检查状态的端点将返回一个代表HealthStatus的字符串值。

如果你配置了多个健康检查,这不实用,因为你希望单独查看每项服务的健康状态。

更糟糕的是,如果其中一项服务失败,整个响应将返回Unhealthy,你不知道问题的原因。

你可以通过提供一个ResponsWriter来解决这个问题,而在AspNetCore.HealthChecks.UI.Client库中就存在这样一个。

让我们安装NuGet包:

Install-Package AspNetCore.HealthChecks.UI.Client

你需要稍微更新对MapHealthChecks的调用,以使用来自此库的ResponseWriter

app.MapHealthChecks( "/health", new HealthCheckOptions { ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse });

做了这些改变之后,健康检查端点的响应看起来是这样的:

{
  "status": "Unhealthy",
  "totalDuration": "00:00:00.3285211",
  "entries": {
    "npgsql": {
      "data": {},
      "duration": "00:00:00.1183517",
      "status": "Healthy",
      "tags": []
    },
    "rabbitmq": {
      "data": {},
      "duration": "00:00:00.1189561",
      "status": "Healthy",
      "tags": []
    },
    "custom-sql": {
      "data": {},
      "description": "无法连接到数据库。",
      "duration": "00:00:00.2431813",
      "exception": "无法连接到数据库。",
      "status": "Unhealthy",
      "tags": []
    }
  }
}

要点

应用程序监控对于跟踪应用程序的可用性、资源使用情况和性能变化很重要。

我之前在云部署中使用了健康检查来实现故障转移情景。当一个应用实例停止回应健康结果时,会创建一个新的实例继续处理请求。

通过暴露健康检查,可以轻松监控ASP.NET Core应用程序的健康状况。

你可以选择实现自定义健康检查,但首先考虑是否有现成的解决方案