在ASP.NET Core中使用健康检查监控您的应用程序
摘要
原文 Health Checks In ASP.NET Core For Monitoring Your Applications 由 Milan Jovanović 发表。
我们都希望构建健壮且可靠的应用程序,这些应用程序能无限扩展并处理任意数量的请求。
但随着分布式系统和微服务架构增长的复杂性,监控我们应用程序的健康变得越来越困难。
拥有一个系统来快速反馈应用程序健康状态是至关重要的。
这就是健康检查的用武之地。
健康检查提供了一种监控和验证应用程序各个组件健康情况的方法,包括:
- 数据库
- API接口
- 缓存
- 外部服务
让我们看看如何在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.Healthy
HealthStatus.Degraded
HealthStatus.Unhealthy
您可以使用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
仓库中,你可以找到用于常用服务和库的广泛集合健康检查包。
这里有一些示例:
- SQL Server -
AspNetCore.HealthChecks.SqlServer
- Postgres -
AspNetCore.HealthChecks.Npgsql
- Redis -
AspNetCore.HealthChecks.Redis
- RabbitMQ -
AspNetCore.HealthChecks.RabbitMQ
- AWS S3 -
AspNetCore.HealthChecks.Aws.S3
- SignalR -
AspNetCore.HealthChecks.SignalR
以下是如何为PostgreSQL和RabbitMQ添加健康检查:
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应用程序的健康状况。
你可以选择实现自定义健康检查,但首先考虑是否有现成的解决方案。