.NET Core Web 中的健康检查端点(Health Check Endpoint)

文章目录
- [.NET Core Web 中的健康检查端点(Health Check Endpoint)](#.NET Core Web 中的健康检查端点(Health Check Endpoint))
-
- 概述
- 核心概念
-
- [1. 健康状况状态](#1. 健康状况状态)
- [2. 主要组件](#2. 主要组件)
- 基本配置
-
- [1. 添加健康检查服务](#1. 添加健康检查服务)
- [2. 配置端点路由](#2. 配置端点路由)
- 创建自定义健康检查
-
- [实现 IHealthCheck 接口](#实现 IHealthCheck 接口)
- 常用内置健康检查
-
- [1. 数据库健康检查](#1. 数据库健康检查)
- [2. URL 健康检查](#2. URL 健康检查)
- [3. 内存检查](#3. 内存检查)
- 高级配置选项
-
- [1. 分组和过滤](#1. 分组和过滤)
- [2. 自定义响应格式](#2. 自定义响应格式)
- [3. 延迟启动和超时设置](#3. 延迟启动和超时设置)
- [Kubernetes 集成示例](#Kubernetes 集成示例)
-
- [1. Pod 配置](#1. Pod 配置)
- [2. 应用程序配置](#2. 应用程序配置)
- [健康检查 UI](#健康检查 UI)
-
- [1. 安装包](#1. 安装包)
- [2. 配置](#2. 配置)
- 最佳实践
-
- [1. 分离检查类型](#1. 分离检查类型)
- [2. 设置适当的超时](#2. 设置适当的超时)
- [3. 避免昂贵的操作](#3. 避免昂贵的操作)
- [4. 安全性考虑](#4. 安全性考虑)
- 监控和警报
-
- [1. 集成 Prometheus](#1. 集成 Prometheus)
- [2. 集成 Application Insights](#2. 集成 Application Insights)
- 示例:完整配置
- 总结
概述
健康检查端点是 ASP.NET Core 提供的一种机制,用于监控应用程序的运行状况,通常用于容器编排(如Kubernetes)、负载均衡器和监控系统。它允许外部系统定期检查应用程序是否正常运行并能够处理请求。
核心概念
1. 健康状况状态
- Healthy:应用程序正常运行
- Degraded:应用程序运行但性能下降
- Unhealthy:应用程序无法正常运行
2. 主要组件
IHealthCheck接口:定义健康检查逻辑- 健康检查中间件:处理健康检查请求
- 健康检查服务:注册和管理检查项
基本配置
1. 添加健康检查服务
csharp
// Program.cs 或 Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// 添加基本健康检查
services.AddHealthChecks();
// 或者添加自定义检查
services.AddHealthChecks()
.AddCheck<DatabaseHealthCheck>("database")
.AddCheck<ExternalApiHealthCheck>("external_api",
failureStatus: HealthStatus.Degraded);
}
2. 配置端点路由
csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// 基本健康检查端点
endpoints.MapHealthChecks("/health");
// 带自定义配置的端点
endpoints.MapHealthChecks("/health/detailed", new HealthCheckOptions
{
ResponseWriter = WriteResponse
});
});
}
创建自定义健康检查
实现 IHealthCheck 接口
csharp
public class DatabaseHealthCheck : IHealthCheck
{
private readonly string _connectionString;
public DatabaseHealthCheck(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("DefaultConnection");
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
var command = connection.CreateCommand();
command.CommandText = "SELECT 1";
await command.ExecuteScalarAsync(cancellationToken);
return HealthCheckResult.Healthy("数据库连接正常");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy(
"数据库连接失败",
exception: ex);
}
}
}
常用内置健康检查
1. 数据库健康检查
csharp
// 添加 NuGet 包:AspNetCore.HealthChecks.SqlServer
services.AddHealthChecks()
.AddSqlServer(
connectionString: Configuration.GetConnectionString("DefaultConnection"),
name: "SQL Server",
failureStatus: HealthStatus.Unhealthy,
tags: new[] { "database", "sql" });
2. URL 健康检查
csharp
// 添加 NuGet 包:AspNetCore.HealthChecks.Uris
services.AddHealthChecks()
.AddUrlGroup(
uri: new Uri("https://api.example.com/health"),
name: "外部API",
failureStatus: HealthStatus.Degraded);
3. 内存检查
csharp
services.AddHealthChecks()
.AddPrivateMemoryHealthCheck(
maximumMegabytes: 1024, // 最大内存限制 1GB
name: "内存使用量");
高级配置选项
1. 分组和过滤
csharp
app.UseEndpoints(endpoints =>
{
// 基本健康检查(仅包含标记为"ready"的检查)
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = (check) => check.Tags.Contains("ready")
});
// 详细健康检查(所有检查)
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = (_) => true
});
});
2. 自定义响应格式
csharp
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json";
var response = new
{
status = result.Status.ToString(),
totalDuration = result.TotalDuration.TotalSeconds.ToString("0:0.00"),
checks = result.Entries.Select(e => new
{
name = e.Key,
status = e.Value.Status.ToString(),
duration = e.Value.Duration.TotalSeconds.ToString("0:0.00"),
description = e.Value.Description,
exception = e.Value.Exception?.Message,
data = e.Value.Data
})
};
return context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
3. 延迟启动和超时设置
csharp
services.AddHealthChecks()
.AddCheck<StartupHealthCheck>(
"启动检查",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" },
timeout: TimeSpan.FromSeconds(30));
Kubernetes 集成示例
1. Pod 配置
yaml
apiVersion: v1
kind: Pod
metadata:
name: aspnetcore-app
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /health/live
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
2. 应用程序配置
csharp
// 启动时检查
services.AddHealthChecks()
.AddCheck<StartupProbe>("启动探针", tags: new[] { "startup" });
// 存活检查
services.AddHealthChecks()
.AddCheck<LivenessProbe>("存活探针", tags: new[] { "live" });
// 就绪检查
services.AddHealthChecks()
.AddCheck<ReadinessProbe>("就绪探针", tags: new[] { "ready" })
.AddCheck<DatabaseHealthCheck>("数据库", tags: new[] { "ready" });
健康检查 UI
1. 安装包
bash
dotnet add package AspNetCore.HealthChecks.UI
dotnet add package AspNetCore.HealthChecks.UI.Client
dotnet add package AspNetCore.HealthChecks.UI.InMemory.Storage
2. 配置
csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddSqlServer(connectionString)
.AddRedis(redisConnectionString);
services.AddHealthChecksUI(settings =>
{
settings.AddHealthCheckEndpoint("API", "/health");
settings.SetEvaluationTimeInSeconds(30); // 每30秒检查一次
settings.SetApiMaxActiveRequests(1); // 同时只允许一个请求
}).AddInMemoryStorage();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
endpoints.MapHealthChecksUI();
});
}
最佳实践
1. 分离检查类型
csharp
// 存活检查:应用是否在运行
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = _ => false // 通常很轻量,甚至可以是空的
});
// 就绪检查:应用是否准备好处理请求
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready")
});
// 启动检查:应用是否完成初始化
endpoints.MapHealthChecks("/health/startup", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("startup")
});
2. 设置适当的超时
csharp
services.AddHealthChecks()
.AddUrlGroup(
new Uri("http://external-service"),
"external_service",
timeout: TimeSpan.FromSeconds(3)); // 快速失败
3. 避免昂贵的操作
csharp
public class LightweightHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken)
{
// 避免复杂的数据库查询或外部API调用
// 使用缓存结果或简单的ping操作
return Task.FromResult(HealthCheckResult.Healthy());
}
}
4. 安全性考虑
csharp
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = WriteResponse
}).RequireAuthorization(); // 需要认证
// 或者为监控系统提供公开端点
endpoints.MapHealthChecks("/health/public");
});
监控和警报
1. 集成 Prometheus
csharp
// 添加包:AspNetCore.HealthChecks.Prometheus.Metrics
services.AddHealthChecks()
.AddPrometheusGatewayPublisher(
"http://prometheus:9091",
"health_metrics",
opts => opts.ReportIntervalSeconds = 30);
2. 集成 Application Insights
csharp
services.AddHealthChecks()
.AddApplicationInsightsPublisher(
saveDetailedReport: true,
instrumentationKey: Configuration["ApplicationInsights:InstrumentationKey"]);
示例:完整配置
csharp
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 添加健康检查服务
builder.Services.AddHealthChecks()
.AddCheck<DatabaseHealthCheck>("database", tags: new[] { "ready", "live" })
.AddCheck<RedisHealthCheck>("cache", tags: new[] { "ready" })
.AddCheck<StartupHealthCheck>("startup", tags: new[] { "startup" })
.AddUrlGroup(new Uri("https://payment.api"), "payment_api", tags: new[] { "ready" })
.AddDiskStorageHealthCheck(s => s.AddDrive("C:\\", 1024)) // 磁盘空间检查
.AddProcessHealthCheck("sqlservr", p => p.Length > 0); // 进程检查
// 配置健康检查UI
builder.Services.AddHealthChecksUI(setup =>
{
setup.AddHealthCheckEndpoint("基本检查", "/health");
setup.AddHealthCheckEndpoint("就绪检查", "/health/ready");
setup.AddHealthCheckEndpoint("存活检查", "/health/live");
}).AddInMemoryStorage();
var app = builder.Build();
// 配置端点
app.MapHealthChecks("/health");
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("ready")
});
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live"),
ResponseWriter = WriteMinimalResponse
});
app.MapHealthChecksUI();
app.Run();
// 最小化响应
static Task WriteMinimalResponse(HttpContext context, HealthReport report)
{
context.Response.ContentType = "application/json";
return context.Response.WriteAsync(
$"{{\"status\":\"{report.Status}\"}}");
}
总结
健康检查端点是现代微服务架构中的重要组件,它:
- 提高可用性:通过快速发现并处理故障
- 支持自动恢复:容器编排系统可以根据健康检查自动重启服务
- 提供监控数据:为运维团队提供应用程序健康状况的实时视图
- 支持渐进式部署:确保新版本完全就绪后再接收流量
通过合理配置健康检查端点,可以显著提高系统的可靠性和可维护性。