当前位置: 首页 > ds >正文

案例——从零开始搭建 ASP.NET Core 健康检查实例

1. 项目创建与基础设置

创建新项目

首先,创建一个新的 ASP.NET Core Web API 项目:

dotnet new webapi -n HealthCheckDemo
cd HealthCheckDemo

添加必要的 NuGet 包

添加健康检查相关的 NuGet 包:

dotnet add package Microsoft.AspNetCore.Diagnostics.HealthChecks
dotnet add package AspNetCore.HealthChecks.SqlServer  # 用于数据库健康检查
dotnet add package AspNetCore.HealthChecks.Redis     # 用于 Redis 健康检查

2. 健康检查原理解析

在深入代码之前,让我们先理解健康检查的核心概念:

  1. 健康检查服务:ASP.NET Core 提供了一个框架,用于报告应用程序及其依赖组件的健康状态
  2. 检查类型
    • 存活检查 (Liveness):应用程序是否正在运行
    • 就绪检查 (Readiness):应用程序是否准备好处理请求
    • 依赖检查:外部依赖(数据库、缓存等)是否可用
  3. 响应格式:健康检查端点返回一个 JSON 对象,包含整体状态和各个检查的详细结果

3. 完整代码实现

Program.cs 完整代码

using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System.Text.Json;
using System.Text.Json.Serialization;var builder = WebApplication.CreateBuilder(args);// 添加服务到容器
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();// 1. 注册健康检查服务
builder.Services.AddHealthChecks()// 2. 添加一个简单的存活检查(总是健康).AddCheck("self", () => HealthCheckResult.Healthy("Application is running"), tags: new[] { "live" })// 3. 添加数据库健康检查(模拟).AddCheck("database", () => {// 模拟数据库检查var isHealthy = CheckDatabaseConnection();return isHealthy ? HealthCheckResult.Healthy("Database connection is OK") : HealthCheckResult.Unhealthy("Database connection failed");}, tags: new[] { "ready", "database" })// 4. 添加 Redis 健康检查(模拟).AddCheck("redis", () => {// 模拟 Redis 检查var isHealthy = CheckRedisConnection();return isHealthy ? HealthCheckResult.Healthy("Redis connection is OK") : HealthCheckResult.Unhealthy("Redis connection failed");}, tags: new[] { "ready", "redis" });// 模拟数据库连接检查方法
bool CheckDatabaseConnection()
{// 在实际应用中,这里会尝试连接到真实数据库// 这里我们模拟90%的成功率return new Random().NextDouble() > 0.1;
}// 模拟 Redis 连接检查方法
bool CheckRedisConnection()
{// 在实际应用中,这里会尝试连接到真实 Redis// 这里我们模拟80%的成功率return new Random().NextDouble() > 0.2;
}var app = builder.Build();// 配置 HTTP 请求管道
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();// 5. 配置健康检查端点// 综合健康检查端点(包含所有检查)
app.MapHealthChecks("/health", new HealthCheckOptions
{// 自定义响应格式ResponseWriter = async (context, report) =>{context.Response.ContentType = "application/json";var response = new{status = report.Status.ToString(),totalDuration = report.TotalDuration.ToString(),checks = report.Entries.Select(e => new{name = e.Key,status = e.Value.Status.ToString(),description = e.Value.Description,duration = e.Value.Duration.ToString()})};await context.Response.WriteAsync(JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = true }));}
});// 存活检查端点(只包含快速的基本检查)
app.MapHealthChecks("/health/live", new HealthCheckOptions
{Predicate = check => check.Tags.Contains("live"),ResponseWriter = WriteHealthCheckResponse
});// 就绪检查端点(包含所有依赖检查)
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{Predicate = check => check.Tags.Contains("ready"),ResponseWriter = WriteHealthCheckResponse
});// 健康检查响应写入器
async Task WriteHealthCheckResponse(HttpContext context, HealthReport report)
{context.Response.ContentType = "application/json";var result = JsonSerializer.Serialize(new{status = report.Status.ToString(),checks = report.Entries.Select(e => new{name = e.Key,status = e.Value.Status.ToString()})});await context.Response.WriteAsync(result);
}app.Run();

添加一个示例控制器

创建 Controllers/TestController.cs

using Microsoft.AspNetCore.Mvc;namespace HealthCheckDemo.Controllers;[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{private static int _requestCount = 0;[HttpGet]public IActionResult Get(){_requestCount++;// 每10个请求模拟一次故障if (_requestCount % 10 == 0){return StatusCode(500, "Simulated server error");}return Ok($"Request #{_requestCount}: Hello from TestController!");}
}

4. 测试健康检查

启动应用程序

dotnet run

测试不同健康检查端点

  1. 综合健康检查(所有检查):

    curl -k https://localhost:7003/health
    
  2. 存活检查(只检查应用本身):

    curl -k https://localhost:7003/health/live
    
  3. 就绪检查(检查应用和所有依赖):

    curl -k https://localhost:7003/health/ready
    

示例响应

成功响应

{"status": "Healthy","totalDuration": "00:00:00.1024567","checks": [{"name": "self","status": "Healthy","description": "Application is running","duration": "00:00:00.0000862"},{"name": "database","status": "Healthy","description": "Database connection is OK","duration": "00:00:00.1001234"},{"name": "redis","status": "Healthy","description": "Redis connection is OK","duration": "00:00:00.1002341"}]
}

失败响应

{"status": "Unhealthy","totalDuration": "00:00:00.2034567","checks": [{"name": "self","status": "Healthy","description": "Application is running","duration": "00:00:00.0000762"},{"name": "database","status": "Unhealthy","description": "Database connection failed","duration": "00:00:00.2001234"},{"name": "redis","status": "Healthy","description": "Redis connection is OK","duration": "00:00:00.2002341"}]
}

5. 与容器编排系统集成

创建 Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["HealthCheckDemo.csproj", "."]
RUN dotnet restore "HealthCheckDemo.csproj"
COPY . .
RUN dotnet build "HealthCheckDemo.csproj" -c Release -o /app/buildFROM build AS publish
RUN dotnet publish "HealthCheckDemo.csproj" -c Release -o /app/publishFROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "HealthCheckDemo.dll"]

Kubernetes 部署配置

创建 deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: healthcheck-demo
spec:replicas: 3selector:matchLabels:app: healthcheck-demotemplate:metadata:labels:app: healthcheck-demospec:containers:- name: healthcheck-demoimage: healthcheck-demo:latestports:- containerPort: 80# 存活探针 - 检查应用是否正在运行livenessProbe:httpGet:path: /health/liveport: 80initialDelaySeconds: 10periodSeconds: 10timeoutSeconds: 5failureThreshold: 3# 就绪探针 - 检查应用是否准备好接收流量readinessProbe:httpGet:path: /health/readyport: 80initialDelaySeconds: 5periodSeconds: 5timeoutSeconds: 3failureThreshold: 1# 启动探针 - 检查应用是否已启动startupProbe:httpGet:path: /health/liveport: 80initialDelaySeconds: 10periodSeconds: 10failureThreshold: 30
---
apiVersion: v1
kind: Service
metadata:name: healthcheck-demo-service
spec:selector:app: healthcheck-demoports:- protocol: TCPport: 80targetPort: 80type: LoadBalancer

6. 高级功能:健康检查 UI

添加健康检查 UI

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

更新 Program.cs

builder.Services.AddHealthChecks() 后添加:

// 添加健康检查 UI 服务
builder.Services.AddHealthChecksUI(setup =>
{setup.AddHealthCheckEndpoint("API", "/health");setup.SetEvaluationTimeInSeconds(60); // 每60秒检查一次setup.SetMinimumSecondsBetweenFailureNotifications(60); // 失败通知最小间隔
})
.AddInMemoryStorage();

在端点映射部分添加:

// 健康检查 UI 端点
app.MapHealthChecksUI(setup => 
{setup.UIPath = "/healthchecks-ui";setup.ApiPath = "/healthchecks-api";
});

现在您可以访问 /healthchecks-ui 查看健康检查的可视化界面。

7. 实际数据库健康检查

替换模拟的数据库检查为真实的 SQL Server 检查:

// 在 Program.cs 的顶部添加
using Microsoft.Data.SqlClient;// 替换模拟的数据库检查
.AddSqlServer(connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),healthQuery: "SELECT 1;", // 简单的健康检查查询name: "sql",failureStatus: HealthStatus.Unhealthy,tags: new[] { "ready", "database" }
)

appsettings.json 中添加连接字符串:

{"ConnectionStrings": {"DefaultConnection": "Server=localhost;Database=master;User Id=sa;Password=YourPassword123;TrustServerCertificate=true;"},// 其他配置...
}

总结

通过这个完整的实例,您已经学会了:

  1. 健康检查的基本概念:存活检查、就绪检查和依赖检查
  2. 如何注册健康检查服务:使用 AddHealthChecks()AddCheck() 方法
  3. 如何创建自定义健康检查:实现简单的检查逻辑
  4. 如何配置健康检查端点:使用 MapHealthChecks() 方法
  5. 如何自定义响应格式:使用 ResponseWriter 选项
  6. 如何与容器编排系统集成:配置 Kubernetes 探针
  7. 如何添加健康检查 UI:使用健康检查 UI 包

健康检查是构建可靠、可观测的分布式系统的关键组件,它可以帮助您及时发现和解决问题,确保应用程序的高可用性。

http://www.xdnf.cn/news/19582.html

相关文章:

  • 齿轮加工刀具材料漫谈:从高速钢到陶瓷的 “切削艺术”
  • 传统数据库out啦!KINGBASE ES V9R1C10 开启国产数据库“修仙”新纪元!
  • Day19_【机器学习—线性回归 (2)】
  • 正则表达式 Python re 库完整教程
  • 生存分析入门教程
  • 馈电油耗讲解
  • AssemblyLoadContext`的插件化架构
  • Qt libcurl的下载、配置及简单测试 (windows环境)
  • springboot项目启动时打印maven打包时间
  • [Mysql数据库] 知识点总结8
  • 计算机网络:(十六)TCP 的运输连接管理
  • Ring Buffer解析
  • 仓颉语言Web框架中的路由分组
  • linux系统学习(6.软件包管理)
  • 十分钟快速掌握 YML YAML 文件
  • 07.《交换机三层功能、单臂路由与端口安全基础知识》
  • 在Linux环境安装Maven(保姆级别)
  • leetcode 面试题 01.01.判定字符是否唯一
  • 【高级】系统架构师 | 信息系统基础
  • 基于Seurat的空转单样本数据分析流程学习(一)
  • JavaScript中的XMLHttpRequest对象分析
  • 基于单片机智能保温杯/智能水杯
  • Java基础第7天总结(代码块、内部类、函数式编程)
  • 【多模态】使用LLM生成html图表
  • 打开多个Excel文件后快速关闭所有的文档,并且退出Excel应用
  • s[:] = reversed(s) 和 s = reversed(s)的区别
  • 【Proteus仿真】点亮小灯系列仿真——小灯闪烁/流水灯/交通灯
  • R3:适用于 .NET 的新一代响应式扩展库,事件订阅流
  • TFS-2002《Fuzzy Clustering With Viewpoints》
  • 嵌入式ARM程序高级调试技能:19.qumu arm elf无法生成coredump