Проверка работоспособности ASP.NET Core в многопользовательской среде с использованием конфигурации маршрутизации

Я начал использовать проверки работоспособности из Asp.net Core, мне они нравятся, но я не смог найти простой способ связать их с маршрутизацией на основе клиентов, например, с поддержкой:

  • /health [общие проверки, не относящиеся к арендатору]
  • /{tenant}/health [проверка клиента]

Если бы я преуспел с этим подходом, я мог бы использовать теги, чтобы отфильтровать, какую проверку работоспособности использовать, но, к сожалению, мне не удалось настроить маршрутизацию для запроса.

app.UseEndpointRouting();
app.UseHealthChecks("/{tenant}/health", new HealthCheckOptions
    {
        ResponseWriter = WriteCustomHealthResponse,
        AllowCachingResponses = false,
        Predicate = _ => _.Tags.Contains("tenant-specific")
    });

Приведенный выше код неправильно маршрутизируется. Я изучил возможность использовать что-то вроде следующего:

app.MapWhen(context => 
    context.Request.Method == HttpMethod.Get.Method &&
    context.Request.?ROUTEDATA?.SOMECHECK("/{tenant}/HealthCheck"),
                builder => builder.UseHealthChecks());

Но в этом случае у меня нет возможности проверить правильность маршрутизации.


person Norcino    schedule 16.09.2019    source источник
comment
Зачем вам это нужно? Проверка работоспособности предназначена для приложения в целом.   -  person Chris Pratt    schedule 16.09.2019
comment
Что ж, я не согласен, в моей архитектуре у меня могут быть проблемы с доступностью, затрагивающие только определенных арендаторов, также у меня есть, например, базы данных для конкретных арендаторов и различные конфигурации, интеграции и т. д., управляемые арендаторами. Я хочу проверить мультитенантные ресурсы (и многое другое), а также специфические для арендатора, о которых я не обязательно знаю, существуют ли они. Возможно, я перегружаю эту функцию, но это действительно дает мне хорошее представление о состоянии системы.   -  person Norcino    schedule 16.09.2019


Ответы (1)


Пока решение, которое я нашел, состоит в том, чтобы использовать параметры строки запроса и использовать IHttpContextAccessor для поиска параметра клиента. Для этого я создал базовую абстрактную реализацию IHealthCheck.

public abstract class BaseTenantHealthCheck : IHealthCheck
{
    private IHttpContextAccessor _httpContextAccessor;

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

    protected string GetTenant()
    {
        return _httpContextAccessor?.HttpContext?.Request?.Query["tenant"].ToString();
    }

    protected bool IsTenantSpecificCheck() => !string.IsNullOrEmpty(GetTenant());

    public abstract Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken));
}

Затем в классе реализации я передаю метод доступа к контексту, показанный ниже.

public class MylAvailabilityHealthCheck : BaseTenantHealthCheck
{
    public MyAvailabilityHealthCheck(IOptionsMonitor<MyAvailabilityCheckOptions> options, IHttpContextAccessor httpContextAccessor)
    : base(httpContextAccessor)
    {
        [..]

Для доступа к проверке работоспособности я использую:

  • http://{url}/health [для мультитенантных проверок]
  • http://{url}/health?tenant=TenantName [для проверок конкретного арендатора]

Я с нетерпением жду, чтобы услышать, есть ли более элегантный способ сделать это.

person Norcino    schedule 16.09.2019
comment
здесь у вас есть хорошая статья о реализации Healthchecks - person Pedro Brito; 16.09.2019
comment
@Norcino - Предполагая, что Asp.Net Core 3.0 (возможно, должен быть 3.1) - вы можете разрешить параметры пути с помощью маршрутизации конечных точек в своей проверке работоспособности. Вам нужно будет внедрить HttpContextAccessor в проверку работоспособности и извлечь объект RouteData из контекста. //In Health Check var routeData = _accessor.HttpContext.GetRouteData(); var databaseName = routeData.Values["nameOfPathParameter"].ToString(); //Startup.cs - ConfigureServices registry .AddHealthChecks() .AddTypeActivatedCheck<SqlServerHealthCheck>("mssql", HealthStatus.Degraded); - person JGx714791; 15.12.2020
comment
Остальная часть кода: app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapHealthChecks("/api/health-check/db/mssql/{nameOfPathParameter}", new HealthCheckOptions { Predicate = SqlServerHealthCheckPredicate }); }); public static Func<HealthCheckRegistration, bool> SqlServerHealthCheckPredicate = registration => registration.Name.Equals("mssql", StringComparison.OrdinalIgnoreCase); - person JGx714791; 15.12.2020
comment
Спасибо JGx714791, я попробую другое сопоставление, которое вы предлагаете. - person Norcino; 15.12.2020