You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AspNetCore.Diagnostics.HealthChecks无法正确识别自定义健康API状态

问题:AspNetCore.Diagnostics.HealthChecks无法正确识别.Net Framework项目的健康状态

场景说明

我使用AspNetCore.Diagnostics.HealthChecks搭建健康检查系统,包含两个项目:

  • .Net Framework项目:自行输出健康报告JSON(格式为[{"Health":"Degraded","Description":"My Project health Check","HttpStatusCode":502}]),接口返回502状态码,但健康检查项目调用后始终显示状态为Healthy。
  • 健康检查项目:通过AddUrlGroup配置对上述项目的检查,但无法正确识别目标接口的健康状态。

核心原因

默认的AddUrlGroup仅判断HTTP请求是否完成(若HttpClient配置了忽略错误状态,非2xx状态码也会被判定为请求成功),不会解析响应体中的健康状态字段,因此无法识别目标接口返回的Degraded状态。

解决方案

需要自定义健康检查逻辑,解析目标接口的响应内容,将返回的健康状态映射到HealthCheck的标准状态,并提取描述信息。

1. 编写自定义健康检查类

创建实现IHealthCheck的类,负责调用目标API并解析响应:

public class CustomApiHealthCheck : IHealthCheck
{
    private readonly HttpClient _httpClient;
    private readonly string _apiEndpoint;

    public CustomApiHealthCheck(HttpClient httpClient, IConfiguration configuration)
    {
        _httpClient = httpClient;
        _apiEndpoint = configuration["HealthCheck:ApiEndpoint"] ?? "http://localhost:2401/api/health/gethealthinfo";
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        try
        {
            var response = await _httpClient.GetAsync(_apiEndpoint, cancellationToken);
            response.EnsureSuccessStatusCode();
            
            var content = await response.Content.ReadAsStringAsync(cancellationToken);
            var healthItems = JsonSerializer.Deserialize<List<CustomHealthResponse>>(content);
            
            if (healthItems == null || !healthItems.Any())
            {
                return HealthCheckResult.Unhealthy("未获取到有效健康检查数据");
            }

            var healthItem = healthItems.First();
            var healthStatus = healthItem.Health switch
            {
                "Healthy" => HealthStatus.Healthy,
                "Degraded" => HealthStatus.Degraded,
                "Unhealthy" => HealthStatus.Unhealthy,
                _ => HealthStatus.Unhealthy
            };

            return new HealthCheckResult(
                healthStatus,
                description: $"{healthItem.Description} (HTTP状态码: {healthItem.HttpStatusCode})"
            );
        }
        catch (HttpRequestException ex)
        {
            return HealthCheckResult.Unhealthy($"API请求失败: {ex.Message}");
        }
        catch (JsonException ex)
        {
            return HealthCheckResult.Unhealthy($"解析健康数据失败: {ex.Message}");
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy($"未知错误: {ex.Message}");
        }
    }
}

// 对应目标API返回的JSON结构模型
public class CustomHealthResponse
{
    public string Health { get; set; }
    public string Description { get; set; }
    public int HttpStatusCode { get; set; }
}

2. 注册自定义健康检查

在Program.cs中替换原有的AddUrlGroup,改为注册自定义健康检查,并配置HttpClient:

// 配置命名HttpClient,复用原有的GetHttpClientHandler逻辑
builder.Services.AddHttpClient("CustomApiHealthClient")
    .ConfigurePrimaryHttpMessageHandler(_ => GetHttpClientHandler());

// 注册自定义健康检查
builder.Services.AddHealthChecks()
    .AddCheck<CustomApiHealthCheck>(
        name: "My Project",
        failureStatus: HealthStatus.Unhealthy,
        tags: new[] { "external-api" }
    );

// 保留HealthChecksUI的原有配置
builder.Services.AddHealthChecksUI()
    .AddInMemoryStorage();

builder.Services.AddControllers();

3. 保留端点配置

原有的端点配置无需修改,确保ResponseWriter正确关联UI响应格式:

app.UseEndpoints(config =>
{
    config.MapHealthChecks("/healthz", new HealthCheckOptions
    {
        Predicate = _ => true,
        ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
    });

    config.MapHealthChecksUI(setup =>
    {
        setup.UIPath = "/show-health-ui";
        setup.ApiPath = "/health-ui-api";
        setup.PageTitle = "My wonderful Health Checks UI";
    });

    config.MapDefaultControllerRoute();
});

可选优化:调整.Net Framework项目的响应格式

将目标API的返回从数组改为单个对象,简化解析逻辑:

{"Health":"Degraded","Description":"My Project health Check","HttpStatusCode":502}

对应的自定义检查中,解析代码改为直接反序列化为CustomHealthResponse即可:

var healthItem = JsonSerializer.Deserialize<CustomHealthResponse>(content);
if (healthItem == null)
{
    return HealthCheckResult.Unhealthy("未获取到有效健康检查数据");
}

内容的提问来源于stack exchange,提问作者N0xus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:34:58