欢迎光临
我们一直在努力

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

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

文章目录

  • .NET Core Web 中的健康检查端点(Health Check Endpoint)
    • 概述
    • 核心概念
      • 1. 健康状况状态
      • 2. 主要组件
    • 基本配置
      • 1. 添加健康检查服务
      • 2. 配置端点路由
    • 创建自定义健康检查
      • 实现 IHealthCheck 接口
    • 常用内置健康检查
      • 1. 数据库健康检查
      • 2. URL 健康检查
      • 3. 内存检查
    • 高级配置选项
      • 1. 分组和过滤
      • 2. 自定义响应格式
      • 3. 延迟启动和超时设置
    • Kubernetes 集成示例
      • 1. Pod 配置
      • 2. 应用程序配置
    • 健康检查 UI
      • 1. 安装包
      • 2. 配置
    • 最佳实践
      • 1. 分离检查类型
      • 2. 设置适当的超时
      • 3. 避免昂贵的操作
      • 4. 安全性考虑
    • 监控和警报
      • 1. 集成 Prometheus
      • 2. 集成 Application Insights
    • 示例:完整配置
    • 总结

概述

健康检查端点是 ASP.NET Core 提供的一种机制,用于监控应用程序的运行状况,通常用于容器编排(如Kubernetes)、负载均衡器和监控系统。它允许外部系统定期检查应用程序是否正常运行并能够处理请求。

核心概念

1. 健康状况状态

  • Healthy:应用程序正常运行
  • Degraded:应用程序运行但性能下降
  • Unhealthy:应用程序无法正常运行

2. 主要组件

  • IHealthCheck 接口:定义健康检查逻辑
  • 健康检查中间件:处理健康检查请求
  • 健康检查服务:注册和管理检查项

基本配置

1. 添加健康检查服务

// Program.cs 或 Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// 添加基本健康检查
services.AddHealthChecks();

// 或者添加自定义检查
services.AddHealthChecks()
.AddCheck<DatabaseHealthCheck>("database")
.AddCheck<ExternalApiHealthCheck>("external_api",
failureStatus: HealthStatus.Degraded);
}

2. 配置端点路由

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();

app.UseEndpoints(endpoints =>
{
// 基本健康检查端点
endpoints.MapHealthChecks("/health");

// 带自定义配置的端点
endpoints.MapHealthChecks("/health/detailed", new HealthCheckOptions
{
ResponseWriter = WriteResponse
});
});
}

创建自定义健康检查

实现 IHealthCheck 接口

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. 数据库健康检查

// 添加 NuGet 包:AspNetCore.HealthChecks.SqlServer
services.AddHealthChecks()
.AddSqlServer(
connectionString: Configuration.GetConnectionString("DefaultConnection"),
name: "SQL Server",
failureStatus: HealthStatus.Unhealthy,
tags: new[] { "database", "sql" });

2. URL 健康检查

// 添加 NuGet 包:AspNetCore.HealthChecks.Uris
services.AddHealthChecks()
.AddUrlGroup(
uri: new Uri("https://api.example.com/health"),
name: "外部API",
failureStatus: HealthStatus.Degraded);

3. 内存检查

services.AddHealthChecks()
.AddPrivateMemoryHealthCheck(
maximumMegabytes: 1024, // 最大内存限制 1GB
name: "内存使用量");

高级配置选项

1. 分组和过滤

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. 自定义响应格式

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. 延迟启动和超时设置

services.AddHealthChecks()
.AddCheck<StartupHealthCheck>(
"启动检查",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" },
timeout: TimeSpan.FromSeconds(30));

Kubernetes 集成示例

1. Pod 配置

apiVersion: v1
kind: Pod
metadata:
name: aspnetcoreapp
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. 应用程序配置

// 启动时检查
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. 安装包

dotnet add package AspNetCore.HealthChecks.UI
dotnet add package AspNetCore.HealthChecks.UI.Client
dotnet add package AspNetCore.HealthChecks.UI.InMemory.Storage

2. 配置

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. 分离检查类型

// 存活检查:应用是否在运行
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. 设置适当的超时

services.AddHealthChecks()
.AddUrlGroup(
new Uri("http://external-service"),
"external_service",
timeout: TimeSpan.FromSeconds(3)); // 快速失败

3. 避免昂贵的操作

public class LightweightHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken)
{
// 避免复杂的数据库查询或外部API调用
// 使用缓存结果或简单的ping操作
return Task.FromResult(HealthCheckResult.Healthy());
}
}

4. 安全性考虑

app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = WriteResponse
}).RequireAuthorization(); // 需要认证

// 或者为监控系统提供公开端点
endpoints.MapHealthChecks("/health/public");
});

监控和警报

1. 集成 Prometheus

// 添加包:AspNetCore.HealthChecks.Prometheus.Metrics
services.AddHealthChecks()
.AddPrometheusGatewayPublisher(
"http://prometheus:9091",
"health_metrics",
opts => opts.ReportIntervalSeconds = 30);

2. 集成 Application Insights

services.AddHealthChecks()
.AddApplicationInsightsPublisher(
saveDetailedReport: true,
instrumentationKey: Configuration["ApplicationInsights:InstrumentationKey"]);

示例:完整配置

// 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}\\"}}");
}

总结

健康检查端点是现代微服务架构中的重要组件,它:

  • 提高可用性:通过快速发现并处理故障
  • 支持自动恢复:容器编排系统可以根据健康检查自动重启服务
  • 提供监控数据:为运维团队提供应用程序健康状况的实时视图
  • 支持渐进式部署:确保新版本完全就绪后再接收流量
  • 通过合理配置健康检查端点,可以显著提高系统的可靠性和可维护性。

    赞(0)
    未经允许不得转载:171主机测评 » .NET Core Web 中的健康检查端点(Health Check Endpoint)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址