0

我有 2 个服务使用 DbContext 中的配置表提供的基本 url 和身份验证发出 Http 请求。

我想实施健康检查以查看服务调用是否成功,例如,我有以下代码:

namespace Company.Api.Infrastructure.HealthChecks
{
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    using Services;
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    public class ExampleServiceHealthCheck : IHealthCheck
    {
        private readonly Guid _sampleOrganizationId = new Guid("8f3a6dd9-6146-4cfa-8ae8-a0fa09998e54");
        private readonly IHttpContextAccessor _httpContextAccessor;

        public ExampleServiceHealthCheck(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            // Trying to create a scope for the service so I don't get concurrent dbContext access exception.
            var exampleService = _httpContextAccessor.HttpContext.RequestServices.GetRequiredService<ExampleService >();
            var invoices = await exampleService.GetInvoicesAsync(_sampleOrganizationId, false);
            if (invoices == null)
            {
                return HealthCheckResult.Unhealthy("Example service didn't return any invoices.");
            }

            return HealthCheckResult.Healthy("Successfully tested Example service with invoices call.");
        }
    }
}

使用一个服务很好,但是当我添加两个都从数据库中获取配置的服务时,我会在其中一个中随机出现此错误。

{
  "status": "Unhealthy",
  "results": {
    "DbContext": {
      "status": "Healthy",
      "description": null,
      "data": {}
    },
    "ExampleService": {
      "status": "Healthy",
      "description": "Successfully tested ExampleService with invoices call.",
      "data": {}
    },
    "ExampleService2": {
      "status": "Unhealthy",
      "description": "An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside \u0027OnConfiguring\u0027 since it is still being configured at this point. This can happen if a second operation is started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.",
      "data": {}
    }
  }
}

这是我的健康检查注册的样子:

public static IServiceCollection AddApplicationHealthChecks(this IServiceCollection services)
{
    services.AddHealthChecks()
        .AddDbContextCheck<DbContext>()
        .AddCheck<ExampleServiceHealthCheck>("ExampleService")
        .AddCheck<ExampleService2HealthCheck>("ExampleService2");

    return services;
}

如何导航此错误?

4

1 回答 1

1

我想我通过在访问这样的服务之前创建一个范围来修复它:我认为这可以确保服务是串行访问数据库而不是并行访问数据库,从而导致上述错误,并且默认情况下,CreateScope如果该方法在某些地方丢失,则会创建一个范围在请求之外。

namespace Company.Api.Infrastructure.HealthChecks
{
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    using Services;
    using System.Threading;
    using System.Threading.Tasks;

    public class ExampleServiceHealthCheck : IHealthCheck
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public ExampleServiceHealthCheck(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            using var serviceScope = _httpContextAccessor.HttpContext.RequestServices.CreateScope(); // <-- This line
            IExampleService exampleService = serviceScope.ServiceProvider.GetRequiredService<IExampleService>();
            var invoices = await exampleService.GetInvoicesAsync();
            if (invoices == null)
            {
                return HealthCheckResult.Unhealthy("Example service didn't return any invoices.");
            }

            return HealthCheckResult.Healthy("Successfully tested Example service with invoices call.");
        }
    }
}
于 2020-12-04T11:33:57.503 回答