缓存运行状况检查网核心

时间:2019-02-21 06:12:53

标签: c# http .net-core asp.net-core-2.2

Net Core 2.2支持执行已发布服务的health checks。 我想缓存检查的响应。

我看到我可以使用HealthCheckOptions并为AllowCachingResponses属性设置true值。

app.UseHealthChecks("/api/services/healthCheck", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions()
            {
                AllowCachingResponses = true
            });

但是我不理解如何设置时间量缓存。设置相应的HTTP标头(Cache-Control, Expires and e.g)的最佳位置是什么?

我的服务是由IIS发布的。

2 个答案:

答案 0 :(得分:0)

您提到的AllowCachingResponses选项仅与HealthCheckMiddleware是否设置HTTP标头有关。通常,中间服务器,代理等可能会缓存GET请求的结果,而这些标头表明服务器应该每次都重新获取它们。

但是,如果您的负载均衡器正在使用这些检查来指示服务是否应该接收更多流量,则可能无论如何都不会缓存结果。

要完成您要寻找的内容,您需要编写其他逻辑。一种方法是编写一种HealthCheckCacher类型,如下所示:

public class HealthCheckCacher : IHealthCheck
{
    private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
    private readonly IHealthCheck _healthCheck;
    private readonly TimeSpan _timeToLive;

    private HealthCheckResult _result;
    private DateTime _lastCheck;

    public static readonly TimeSpan DefaultTimeToLive = TimeSpan.FromSeconds(30);

    /// <summary>
    /// Creates a new HealthCheckCacher which will cache the result for the amount of time specified.
    /// </summary>
    /// <param name="healthCheck">The underlying health check to perform.</param>
    /// <param name="timeToLive">The amount of time for which the health check should be cached. Defaults to 30 seconds.</param>
    public HealthCheckCacher(IHealthCheck healthCheck, TimeSpan? timeToLive = null)
    {
        _healthCheck = healthCheck;
        _timeToLive = timeToLive ?? DefaultTimeToLive;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // you could improve thread concurrency by separating the read/write logic but this would require additional thread safety checks.
        // will throw OperationCanceledException if the token is canceled while we're waiting.
        await _mutex.WaitAsync(cancellationToken);

        try
        {
            // previous check is cached & not yet expired; just return it
            if (_lastCheck > DateTime.MinValue && DateTime.Now - _lastCheck < _timeToLive)
                return _result;

            // check has not been performed or is expired; run it now & cache the result
            _result = await _healthCheck.CheckHealthAsync(context, cancellationToken);
            _lastCheck = DateTime.Now;

            return _result;
        }
        finally
        {
            _mutex.Release();
        }
    }
}

答案 1 :(得分:0)

我的 API 中有一个计划作业,它调用 HealthCheckService.CheckHealthAsync() 并存储 HealthReport 结果。然后我只创建返回此值的常规 API 端点。更简单,不需要人工包装器健康检查。