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

.NET健康检查能否基于前置检查结果设置运行时条件?

.NET健康检查的依赖执行控制方案

当然可以实现仅在前序检查健康时才执行后续检查的需求,以下是两种可行的实现方式:

方式一:在后续检查中前置验证依赖检查状态

直接在TokenHealthCheck和DownloadHealthCheck的检查逻辑里,先验证前置检查的结果,只有前置通过才执行自身的检查逻辑。这种方式无需修改健康检查的注册流程,实现简单。

修改TokenHealthCheck

public class TokenHealthCheck : IHealthCheck
{
    private readonly HealthCheckService _healthCheckService;

    public TokenHealthCheck(HealthCheckService healthCheckService)
    {
        _healthCheckService = healthCheckService;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // 先执行并验证证书检查结果
        var certCheckResult = await _healthCheckService.CheckHealthAsync(
            check => check.Name == "Find-certificate",
            cancellationToken);

        if (certCheckResult.Status != HealthStatus.Healthy)
        {
            // 前置检查失败,直接返回跳过状态(.NET 6+支持)
            return HealthCheckResult.Skipped("依赖的证书检查未通过,跳过令牌请求检查");
        }

        // 执行原本的令牌请求逻辑
        try
        {
            // 此处编写获取访问令牌的业务代码
            return HealthCheckResult.Healthy("令牌请求成功");
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy("令牌请求失败", ex);
        }
    }
}

修改DownloadHealthCheck

public class DownloadHealthCheck : IHealthCheck
{
    private readonly HealthCheckService _healthCheckService;

    public DownloadHealthCheck(HealthCheckService healthCheckService)
    {
        _healthCheckService = healthCheckService;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // 先执行并验证令牌检查结果
        var tokenCheckResult = await _healthCheckService.CheckHealthAsync(
            check => check.Name == "Request-token",
            cancellationToken);

        if (tokenCheckResult.Status != HealthStatus.Healthy)
        {
            return HealthCheckResult.Skipped("依赖的令牌检查未通过,跳过自定义服务检查");
        }

        // 执行原本的自定义服务访问逻辑
        try
        {
            // 此处编写调用自定义服务的业务代码
            return HealthCheckResult.Healthy("自定义服务访问成功");
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy("自定义服务访问失败", ex);
        }
    }
}

方式二:自定义健康检查服务,集中管理依赖链

如果需要更优雅地管理所有检查的依赖关系,避免在每个检查中重复验证逻辑,可以自定义HealthCheckService,控制检查的执行顺序和依赖条件。

实现自定义HealthCheckService

public class CustomHealthCheckService : HealthCheckService
{
    private readonly IEnumerable<IHealthCheck> _healthChecks;
    private readonly IServiceProvider _serviceProvider;

    // 定义检查的依赖关系:key为当前检查名称,value为依赖的前置检查名称列表
    private readonly Dictionary<string, List<string>> _checkDependencies = new()
    {
        { "Request-token", new List<string> { "Find-certificate" } },
        { "CustomService", new List<string> { "Request-token" } }
    };

    public CustomHealthCheckService(IEnumerable<IHealthCheck> healthChecks, IServiceProvider serviceProvider)
        : base(healthChecks, serviceProvider)
    {
        _healthChecks = healthChecks;
        _serviceProvider = serviceProvider;
    }

    public override async Task<HealthReport> CheckHealthAsync(Func<HealthCheckRegistration, bool>? predicate = null, CancellationToken cancellationToken = default)
    {
        var allRegistrations = base.GetRegistrations(predicate).ToList();
        var checkResults = new Dictionary<string, HealthCheckResult>();
        var executedChecks = new HashSet<string>();

        // 先执行无依赖的检查(数据库、证书检查)
        foreach (var registration in allRegistrations.Where(r => !_checkDependencies.ContainsKey(r.Name)))
        {
            var result = await ExecuteSingleCheckAsync(registration, cancellationToken);
            checkResults[registration.Name] = result;
            executedChecks.Add(registration.Name);
        }

        // 循环执行有依赖的检查,直到所有检查完成或无法满足依赖
        var remainingRegistrations = allRegistrations.Where(r => _checkDependencies.ContainsKey(r.Name)).ToList();
        while (remainingRegistrations.Any())
        {
            // 找到所有前置依赖已通过的检查
            var executableCheck = remainingRegistrations.FirstOrDefault(reg => 
                _checkDependencies[reg.Name].All(dep => 
                    executedChecks.Contains(dep) && checkResults[dep].Status == HealthStatus.Healthy));

            if (executableCheck == null)
            {
                // 剩余检查无法满足依赖,标记为跳过
                foreach (var reg in remainingRegistrations)
                {
                    checkResults[reg.Name] = HealthCheckResult.Skipped("依赖的前置检查未通过,无法执行");
                    executedChecks.Add(reg.Name);
                }
                break;
            }

            // 执行当前检查
            var result = await ExecuteSingleCheckAsync(executableCheck, cancellationToken);
            checkResults[executableCheck.Name] = result;
            executedChecks.Add(executableCheck.Name);
            remainingRegistrations.Remove(executableCheck);
        }

        // 生成最终健康报告
        var overallStatus = checkResults.Values.Max(r => r.Status);
        var totalDuration = TimeSpan.FromMilliseconds(checkResults.Sum(r => r.Value.Duration.TotalMilliseconds));
        return new HealthReport(checkResults, totalDuration, overallStatus);
    }

    // 执行单个健康检查的通用方法
    private async Task<HealthCheckResult> ExecuteSingleCheckAsync(HealthCheckRegistration registration, CancellationToken cancellationToken)
    {
        using var scope = _serviceProvider.CreateScope();
        var healthCheck = registration.Factory(scope.ServiceProvider);
        var context = new HealthCheckContext { Registration = registration };
        return await healthCheck.CheckHealthAsync(context, cancellationToken);
    }
}

替换默认的HealthCheckService

在Program.cs中注册自定义服务,替换默认实现:

_builder.Services.AddSingleton<HealthCheckService, CustomHealthCheckService>();

方案选择

  • 如果需求简单,推荐方式一,代码改动小,快速实现目标;
  • 如果需要管理多个检查的复杂依赖关系,推荐方式二,逻辑集中,可维护性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:13:26