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

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

总结

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

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

通过合理配置健康检查端点,可以显著提高系统的可靠性和可维护性。

相关推荐
rosmis2 小时前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript
css趣多多2 小时前
解决ui组件flex1容器底部被撑开的问题
前端
乔江seven2 小时前
【python轻量级Web框架 Flask 】2 构建稳健 API:集成 MySQL 参数化查询与 DBUtils 连接池
前端·python·mysql·flask·web
Alaaaaaaan2 小时前
[DevOps]使用github-action工具部署docker容器(实现提交代码一键推送部署到服务器)
服务器·前端·docker·容器·github
摇滚侠3 小时前
css 设置边框
前端·css
星爷AG I3 小时前
9-24 视觉叙事(AGI基础理论)
前端·人工智能
2501_940007893 小时前
Flutter for OpenHarmony三国杀攻略App实战 - 鸿蒙适配与打包发布
前端·flutter
css趣多多3 小时前
跨域问题及Vue项目中本地/线上解决方法核心总结
前端
光影少年3 小时前
前端 AIGC
前端·aigc