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
相关产品推荐
相关产品推荐

