ASP.NET Core 框架原生健康检查服务详解

在ASP.NET Core 框架中自带原生提供的核心扩展方法AddHealthChecks,用于注册和配置应用的健康检查服务------ 它允许你定义一系列检查项(如数据库连接、缓存服务、外部 API 依赖等),通过标准化的接口暴露应用及依赖的健康状态,是监控系统、容器编排(如 K8s)判断应用是否正常运行的核心能力。

一、核心作用与使用场景

  • 核心作用:向依赖注入容器注册健康检查相关服务,并添加自定义的健康检查项;
  • 典型场景
    • 检查数据库(SQL Server/MySQL/PostgreSQL)是否可连接;
    • 检查缓存(Redis/Memcached)是否可用;
    • 检查外部依赖(如 MQTT Broker、第三方 API)是否正常;
    • 检查磁盘空间、内存使用率等系统资源;
    • 自定义业务健康检查(如订单队列长度、定时任务是否执行)。

二、完整使用示例(可直接运行)

1. 安装基础包(核心 + 常用检查项)

复制代码
# 原生健康检查核心包(已包含在ASP.NET Core Web模板中)
Install-Package Microsoft.Extensions.Diagnostics.HealthChecks

# 常用扩展包(按需安装)
Install-Package AspNetCore.HealthChecks.SqlServer  # SQL Server检查
Install-Package AspNetCore.HealthChecks.Redis     # Redis检查
Install-Package AspNetCore.HealthChecks.Mqtt      # MQTT检查
Install-Package AspNetCore.HealthChecks.System    # 系统资源(磁盘/内存)检查
  1. Program.cs 完整配置

    using Microsoft.AspNetCore.Diagnostics.HealthChecks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    using System.Net.Mime;
    using System.Text.Json;

    var builder = WebApplication.CreateBuilder(args);

    // 核心步骤:注册健康检查服务 + 添加检查项
    builder.Services.AddHealthChecks()
    // 1. 检查SQL Server数据库连接
    .AddSqlServer(
    connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),
    name: "SQL Server", // 检查项名称(用于标识)
    failureStatus: HealthStatus.Unhealthy, // 失败时的状态(Unhealthy/Degraded/Healthy)
    tags: new[] { "database", "storage" }) // 标签(用于筛选检查项)
    // 2. 检查Redis缓存
    .AddRedis(
    redisConnectionString: builder.Configuration["Redis:ConnectionString"],
    name: "Redis Cache",
    failureStatus: HealthStatus.Degraded, // 缓存故障仅标记为"降级",不影响应用整体状态
    tags: new[] { "cache" })
    // 3. 检查MQTT Broker连接
    .AddMqtt(
    mqttBroker: builder.Configuration["MqttBroker:Server"],
    port: int.Parse(builder.Configuration["MqttBroker:Port"] ?? "1883"),
    name: "MQTT Broker",
    tags: new[] { "message", "mq" })
    // 4. 检查外部API依赖
    .AddUrlGroup(
    new Uri(builder.Configuration["ExternalApi:HealthUrl"]!),
    name: "Payment API",
    failureStatus: HealthStatus.Degraded,
    tags: new[] { "external", "api" })
    // 5. 检查磁盘空间(系统资源)
    .AddDiskStorageHealthCheck(
    options =>
    {
    options.AddDrive("/", minimumFreeMegabytes: 1024); // 根目录剩余空间≥1GB
    },
    name: "Disk Storage",
    tags: new[] { "system" })
    // 6. 自定义健康检查项(业务逻辑)
    .AddCheck("Order Queue Health", () =>
    {
    // 模拟检查:订单队列长度是否超过阈值
    var queueLength = GetOrderQueueLength(); // 你的业务方法
    if (queueLength > 1000)
    {
    return HealthCheckResult.Degraded($"订单队列长度超限:{queueLength}");
    }
    return HealthCheckResult.Healthy("订单队列状态正常");
    }, tags: new[] { "business", "queue" });

    // 常规服务注册
    builder.Services.AddControllers();

    var app = builder.Build();

    // 配置健康检查接口(暴露状态)
    app.MapHealthChecks("/health", new HealthCheckOptions
    {
    // 筛选要执行的检查项(按标签/全部)
    // 示例1:只执行"database"标签的检查项
    // Predicate = check => check.Tags.Contains("database"),
    // 示例2:执行所有检查项(默认)
    Predicate = _ => true,

    复制代码
     // 自定义响应格式(默认返回JSON,可改为自定义格式)
     ResponseWriter = async (context, report) =>
     {
         context.Response.ContentType = MediaTypeNames.Application.Json;
         var result = JsonSerializer.Serialize(new
         {
             status = report.Status.ToString(), // 整体状态(Healthy/Degraded/Unhealthy)
             checks = report.Entries.Select(entry => new
             {
                 name = entry.Key,
                 status = entry.Value.Status.ToString(),
                 description = entry.Value.Description,
                 duration = entry.Value.Duration.TotalMilliseconds + "ms",
                 tags = entry.Value.Tags
             }),
             totalDuration = report.TotalDuration.TotalMilliseconds + "ms"
         });
         await context.Response.WriteAsync(result);
     },
    
     // 失败时的HTTP状态码(默认503 Service Unavailable)
     ResultStatusCodes =
     {
         [HealthStatus.Healthy] = StatusCodes.Status200OK,
         [HealthStatus.Degraded] = StatusCodes.Status200OK,
         [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
     }

    });

    // 可选:单独暴露数据库检查接口(用于专项监控)
    app.MapHealthChecks("/health/database", new HealthCheckOptions
    {
    Predicate = check => check.Tags.Contains("database")
    });

    // 常规中间件配置
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.MapControllers();

    app.Run();

    // 模拟业务方法:获取订单队列长度
    int GetOrderQueueLength()
    {
    // 实际场景中替换为真实的队列查询逻辑
    return new Random().Next(0, 1500);
    }

  2. 配置文件示例(appsettings.json)

    {
    "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=MyAppDB;Trusted_Connection=True;"
    },
    "Redis": {
    "ConnectionString": "localhost:6379"
    },
    "MqttBroker": {
    "Server": "mqtt.example.com",
    "Port": 8883
    },
    "ExternalApi": {
    "HealthUrl": "https://payment-api.example.com/health"
    }
    }

三、核心概念与配置说明

1. 健康状态(HealthStatus)

ASP.NET Core 定义了三种核心健康状态,用于标识检查项 / 应用的状态:

状态 含义 典型场景
Healthy 健康 检查项正常,应用可正常提供服务
Degraded 降级 检查项有轻微异常,但应用核心功能仍可用(如缓存不可用,但数据库可用)
Unhealthy 不健康 检查项严重故障,应用核心功能受影响(如数据库连接失败)

2. AddHealthChecks 核心扩展方法

AddHealthChecks 返回 IHealthChecksBuilder,可链式调用以下方法添加检查项:

方法 作用 示例
AddCheck(string, IHealthCheck) 添加自定义健康检查项 AddCheck("Custom Check", new MyCustomHealthCheck())
AddSqlServer/AddMySql/AddPostgres 检查关系型数据库 AddSqlServer(connStr, name: "SQL Server")
AddRedis/AddMemcached 检查缓存服务 AddRedis(redisConnStr, name: "Redis")
AddUrlGroup 检查 HTTP/HTTPS 端点 AddUrlGroup(new Uri("https://api.example.com/health"))
AddDiskStorageHealthCheck 检查磁盘空间 AddDiskStorageHealthCheck(opts => opts.AddDrive("/", 1024))

3. 关键配置项(HealthCheckOptions)

MapHealthChecks 时配置的 HealthCheckOptions 用于控制健康检查接口的行为:

  • Predicate:筛选要执行的检查项(按名称 / 标签);
  • ResponseWriter:自定义响应格式(默认返回 JSON,可改为 XML / 自定义结构);
  • ResultStatusCodes:映射健康状态到 HTTP 状态码(如 Unhealthy 返回 503);
  • AllowCachingResponses:是否允许缓存响应(生产环境建议禁用)。

四、访问与验证

  1. 启动应用后,访问以下接口查看健康状态:

    • 全部检查项:https://localhost:5001/health
    • 仅数据库检查:https://localhost:5001/health/database
  2. 典型响应示例(JSON):

    {
    "status": "Healthy",
    "checks": [
    {
    "name": "SQL Server",
    "status": "Healthy",
    "description": null,
    "duration": "12.34ms",
    "tags": ["database", "storage"]
    },
    {
    "name": "Order Queue Health",
    "status": "Degraded",
    "description": "订单队列长度超限:1050",
    "duration": "5.67ms",
    "tags": ["business", "queue"]
    }
    ],
    "totalDuration": "20.11ms"
    }

五、进阶用法:自定义健康检查项

如果内置检查项无法满足需求,可自定义 IHealthCheck 实现:

复制代码
// 自定义健康检查类
public class OrderQueueHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        // 1. 执行业务检查逻辑
        var queueLength = GetOrderQueueLength();
        
        // 2. 根据结果返回健康状态
        if (queueLength > 1000)
        {
            return Task.FromResult(HealthCheckResult.Degraded(
                $"订单队列长度超限:{queueLength}(阈值:1000)"));
        }
        
        return Task.FromResult(HealthCheckResult.Healthy("订单队列状态正常"));
    }

    private int GetOrderQueueLength()
    {
        // 真实场景中替换为查询消息队列(如RabbitMQ/Kafka)的逻辑
        return new Random().Next(0, 1500);
    }
}

// 注册自定义检查项
builder.Services.AddHealthChecks()
    .AddCheck<OrderQueueHealthCheck>("Order Queue Health", tags: new[] { "business" });

总结

  1. AddHealthChecks 是ASP.NET Core 注册健康检查服务的核心方法,可添加内置 / 自定义检查项;
  2. 核心配置包括:检查项(数据库 / 缓存 / 外部 API)、状态映射、响应格式;
  3. 通过 MapHealthChecks 暴露 HTTP 接口,可结合 AddHealthChecksUI 实现可视化监控,是生产环境必备的监控能力。

ASP.NET Core 生态中AddHealthChecksUI( AspNetCore.HealthChecks.UI 库的核心扩展方法),专门用于注册和配置健康检查可视化面板的服务 ------ 它基于原生 AddHealthChecks 提供的健康检查数据,生成直观的 Web UI 界面,让你无需解析 JSON 就能快速查看所有检查项的状态、历史记录和故障详情。

一、核心定位与依赖关系

AddHealthChecksUI 是对原生健康检查的可视化增强,使用前必须满足两个前提:

  1. 已通过 AddHealthChecks 注册原生健康检查项(数据库、Redis、API 等);
  2. 已安装对应的 NuGet 包(UI 核心包 + 存储包)。

二、完整且规范的使用示例

1. 安装全套依赖包

复制代码
# UI核心包(必须)
Install-Package AspNetCore.HealthChecks.UI
# UI客户端(适配原生健康检查接口的响应格式,必须)
Install-Package AspNetCore.HealthChecks.UI.Client
# 存储包(二选一:开发用内存,生产用SQLite)
Install-Package AspNetCore.HealthChecks.UI.InMemory.Storage  # 开发环境
Install-Package AspNetCore.HealthChecks.UI.Sqlite.Storage    # 生产环境
  1. Program.cs 完整配置(分步骤)

    using HealthChecks.UI.Client;
    using Microsoft.AspNetCore.Diagnostics.HealthChecks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;

    var builder = WebApplication.CreateBuilder(args);

    // ===================== 第一步:注册原生健康检查(基础) =====================
    builder.Services.AddHealthChecks()
    // 示例1:检查SQL Server数据库
    .AddSqlServer(
    connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),
    name: "SQL Server",
    failureStatus: HealthStatus.Unhealthy,
    tags: new[] { "database" })
    // 示例2:检查Redis缓存
    .AddRedis(
    redisConnectionString: builder.Configuration["Redis:ConnectionString"],
    name: "Redis",
    failureStatus: HealthStatus.Degraded,
    tags: new[] { "cache" })
    // 示例3:检查外部API
    .AddUrlGroup(
    new Uri("https://api.example.com/health"),
    name: "Payment API",
    tags: new[] { "external" });

    // ===================== 第二步:注册UI服务(核心配置) =====================
    builder.Services.AddHealthChecksUI(options =>
    {
    // 1. 配置存储(核心:决定检查结果是否持久化)
    if (builder.Environment.IsDevelopment())
    {
    // 开发环境:内存存储(重启后丢失数据)
    options.AddInMemoryStorage();
    }
    else
    {
    // 生产环境:SQLite持久化存储(推荐,轻量且无需数据库服务)
    var sqliteConnStr = "Data Source=./healthchecks.db"; // 存储路径
    options.AddSqliteStorage(sqliteConnStr);
    }

    复制代码
     // 2. 配置UI自动刷新和通知规则
     options.SetEvaluationTimeInSeconds(15); // 每15秒自动检查一次(默认30秒)
     options.SetMinimumSecondsBetweenFailureNotifications(60); // 故障通知最小间隔60秒
     options.MaximumHistoryEntriesPerEndpoint(100); // 每个检查项保留100条历史记录
    
     // 3. 配置要监控的健康检查端点(关键:指向原生健康检查接口)
     options.AddHealthCheckEndpoint(
         name: "My App", // UI中显示的应用名称
         uri: "/health"); // 原生健康检查接口地址
    
     // 4. 可选:自定义UI显示配置
     options.SetApiMaxActiveRequests(10); // 最大并发检查请求数
     options.DisableMigrations(); // 禁用自动数据库迁移(生产环境建议手动执行)

    })
    // 可选:添加多语言支持(如中文)
    .AddLocalization(options => options.ResourcesPath = "HealthChecksResources");

    // ===================== 第三步:常规服务注册 =====================
    builder.Services.AddControllers();
    builder.Services.AddHealthChecksUI() // 若需重复配置,可链式调用(实际建议集中配置)
    .AddWebhookNotificationPublisher(options =>
    {
    // 可选:配置故障webhook通知(如钉钉/企业微信)
    options.AddWebhook("DingTalk", "https://oapi.dingtalk.com/robot/send?access_token=xxx")
    .SetPayloadCreator((name, report) => new
    {
    msgtype = "text",
    text = new { content = $"【健康检查告警】{name} 状态异常:{report.Status}" }
    })
    .SetFailureStatusCodes(HealthStatus.Unhealthy); // 仅Unhealthy状态触发通知
    });

    var app = builder.Build();

    // ===================== 第四步:配置路由(暴露UI和原生接口) =====================
    // 1. 原生健康检查接口(适配UI格式)
    app.MapHealthChecks("/health", new HealthCheckOptions
    {
    Predicate = _ => true, // 包含所有检查项
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, // 必须:让UI能解析响应
    ResultStatusCodes =
    {
    [HealthStatus.Healthy] = StatusCodes.Status200OK,
    [HealthStatus.Degraded] = StatusCodes.Status200OK,
    [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
    }
    });

    // 2. 健康检查UI面板(核心访问入口)
    app.MapHealthChecksUI(setup =>
    {
    setup.UIPath = "/health-dashboard"; // UI访问地址:https://你的域名/health-dashboard
    setup.ApiPath = "/health-ui-api"; // UI内部接口地址(默认,可自定义)
    setup.PageTitle = "我的应用健康监控面板"; // 自定义页面标题
    });

    // 常规中间件
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.MapControllers();

    app.Run();

  2. 配置文件(appsettings.json)补充

    {
    "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=MyApp;Trusted_Connection=True;"
    },
    "Redis": {
    "ConnectionString": "localhost:6379,password=123456"
    },
    // 可选:将UI配置移到配置文件(解耦代码)
    "HealthChecksUI": {
    "EvaluationTimeInSeconds": 15,
    "MinimumSecondsBetweenFailureNotifications": 60,
    "HealthChecks": [
    {
    "Name": "My App",
    "Uri": "/health"
    }
    ],
    "Storage": {
    "Type": "Sqlite",
    "ConnectionString": "Data Source=./healthchecks.db"
    }
    }
    }

从配置文件加载 UI 配置(替代硬编码)

复制代码
// 替代硬编码的AddHealthCheckEndpoint和AddSqliteStorage
builder.Services.AddHealthChecksUI()
    .AddConfigurationFromSettings(builder.Configuration); // 从HealthChecksUI节点加载配置

三、AddHealthChecksUI 核心配置项详解

配置方法 作用 适用场景
AddInMemoryStorage() 内存存储检查结果 开发 / 测试环境(重启丢失数据)
AddSqliteStorage(string connStr) SQLite 持久化存储 生产环境(轻量、无需额外数据库)
AddSqlServerStorage(string connStr) SQL Server 存储 企业级生产环境(已有 SQL Server)
SetEvaluationTimeInSeconds(int) UI 自动刷新间隔 高频检查(如 10-30 秒)/ 低频检查(如 60 秒)
AddHealthCheckEndpoint(string name, string uri) 添加要监控的健康检查端点 单应用监控 / 多应用集中监控(可添加多个端点)
SetMinimumSecondsBetweenFailureNotifications(int) 故障通知防抖间隔 避免短时间内重复发送告警(如网络抖动)
AddWebhookNotificationPublisher() 配置 webhook 通知 故障时推送告警到钉钉 / 企业微信 / 邮件

四、UI 面板核心功能与访问

启动应用后,访问 https://localhost:5001/health-dashboard 即可看到 UI 面板,核心功能包括:

  1. 状态概览页:所有检查项的实时状态(绿色 = 健康、黄色 = 降级、红色 = 不健康);
  2. 详情页:点击检查项可查看响应时间、故障原因、执行日志;
  3. 历史趋势页:以图表展示检查项状态变化(需持久化存储);
  4. 通知中心:查看已触发的故障通知记录;
  5. 多应用监控 :添加多个AddHealthCheckEndpoint可监控多个应用的健康状态。

五、生产环境关键优化

  1. 存储持久化 :必须替换AddInMemoryStorageAddSqliteStorage/AddSqlServerStorage,避免重启丢失历史数据;

  2. 权限控制:给 UI 路由添加认证,防止未授权访问:

    app.MapHealthChecksUI().RequireAuthorization(); // 需先配置认证(如JWT/Cookie)

  3. 资源限制 :通过SetApiMaxActiveRequests限制并发检查请求数,避免压垮应用;

  4. 监控告警 :配置AddWebhookNotificationPublisher实现故障自动告警(钉钉 / 企业微信 / 邮件);

  5. 静态资源缓存:UI 的静态资源(CSS/JS)可配置缓存,提升访问速度。

总结

  1. AddHealthChecksUI 是注册健康检查可视化 UI 的核心方法,必须配合原生AddHealthChecks使用
  2. 核心配置重点是「存储方式」(内存 / 持久化)、「刷新间隔」、「监控端点」;
  3. 生产环境需优先配置持久化存储、权限控制和故障告警,才能充分发挥 UI 的监控价值。
相关推荐
浮尘笔记11 小时前
Go语言临时对象池:sync.Pool的原理与使用
开发语言·后端·golang
梦梦代码精12 小时前
BuildingAI vs Dify vs 扣子:三大开源智能体平台架构风格对比
开发语言·前端·数据库·后端·架构·开源·推荐算法
REDcker13 小时前
RESTful API设计规范详解
服务器·后端·接口·api·restful·博客·后端开发
没有bug.的程序员15 小时前
Java 序列化:Serializable vs. Protobuf 的性能与兼容性深度对比
java·开发语言·后端·反射·序列化·serializable·protobuf
我爱娃哈哈16 小时前
SpringBoot + Spring Security + RBAC:企业级权限模型设计与动态菜单渲染实战
spring boot·后端·spring
小王不爱笑13217 小时前
SpringBoot 配置文件
java·spring boot·后端
想用offer打牌18 小时前
Spring AI vs Spring AI Alibaba
java·人工智能·后端·spring·系统架构
码农幻想梦19 小时前
实验五 spring入门及IOC实验
java·后端·spring
a程序小傲19 小时前
蚂蚁Java面试被问:向量数据库的相似度搜索和索引构建
开发语言·后端·python·架构·flask·fastapi