首页 > 解决方案 > 为长时间运行的进程 .Net Core 实施 HealthChecks

问题描述

我有一个长期运行的进程:IHostedService。它整天运行,调用不同的外部 api(服务)来提取数据。如果在此过程中任何这些外部服务失败/抛出异常,该过程花费的时间超过 30 分钟等,我想得到通知。我将如何设置它?

经过一番研究,我最终得到了这个: https ://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0#separate-readiness-and- liveness -probes(StartupHostedServiceHealthCheck 部分)

如何在托管服务上实施 .NET Core 健康检查?

这是我到目前为止所拥有的:

// Registered as Singleton
public interface IHostedServiceStatus
{
    bool IsHostedServiceRunning { get; set; }
    DateTime RunTime { get; }
    string Message { get; }

    void Setup(string name, DateTime runTime, string message = null);
}

public class HostedServiceStatus : IHostedServiceStatus
{
    private string _message;
    private string _name;

    public string Message => $"HostedService {_name} started on: {RunTime} failed to complete. {_message}";
    public bool IsHostedServiceRunning { get; set; }
    public DateTime RunTime { get; private set; }

    public void Setup(string name, DateTime runTime, string message = null)
    {
        _name = name;
        RunTime = runTime;

        IsHostedServiceRunning = true;

        if (!string.IsNullOrEmpty(message))
            _message = message;
    }
}

// HealthCheck
public class HostedServiceHealthCheck : IHealthCheck
{
    private readonly IHostedServiceStatus _hostedServiceStatus;
    private readonly TimeSpan _duration = TimeSpan.FromMinutes(30);

    public HostedServiceHealthCheck(IHostedServiceStatus hostedServiceStatus)
    {
        _hostedServiceStatus = hostedServiceStatus;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        if (_hostedServiceStatus.IsHostedServiceRunning)
        {
            if (_hostedServiceStatus.RunTime.Subtract(DateTime.Now).Duration() >= _duration)
                return Task.FromResult(
                    HealthCheckResult.Unhealthy(_hostedServiceStatus.Message));
        }

        return Task.FromResult(
            HealthCheckResult.Healthy("Task is finished."));
    }
}


// Long running process
public async void Process(object state)
{
    // each service runs about 10 min
    foreach (var externalService in externalServices)
    {
        try
        {
            _hostedServiceStatus.Setup(externalService.Name, DateTime.Now); // setup healthcheckStatus - injected
            ...
            // calls externalService gets data and saves to db
            
            
            _dataMinerStatus.IsHostedServiceRunning = false; // udpate Healthcheck - finished successfully
        }
        catch (Exception ex)
        {
            // set MInDateTime so that it becamse UnHealthy
            _hostedServiceStatus.Setup(externalService.Name, DateTime.MinValue); 
            // HealthCheck injected
            await _healthCheck.CheckHealthAsync(new HealthCheckContext()); // send notification? (webhook setup) - will this work?
        }
}

标签: c#.net.net-corehealth-check

解决方案


推荐阅读