如何在ASP.NET Core健康检查中注入依赖项

时间:2018-08-26 15:56:57

标签: c# asp.net-core dependency-injection .net-core health-monitoring

我正在尝试使用新的ASP.NET Code 2.2 Healthchecks功能。

在.net博客的link中,它显示了一个示例:

public void ConfigureServices(IServiceCollection services)
{
    //...
    services
        .AddHealthChecks()
        .AddCheck(new SqlConnectionHealthCheck("MyDatabase", Configuration["ConnectionStrings:DefaultConnection"]));
    //...
}

public void Configure(IApplicationBuilder app)
{
    app.UseHealthChecks("/healthz");
}

我可以添加实现Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck接口的自定义检查。但是,由于我需要向AddCheck方法提供实例而不是类型,并且它需要在ConfigureServices方法内部运行,因此无法在自定义检查器中注入任何依赖项。

有什么办法可以解决此问题?

4 个答案:

答案 0 :(得分:5)

简短回答

  

如何在ASP.NET Core健康检查中注入依赖项。

如果我们以正确的顺序注册我们的服务,那么SomeDependency将可以注入到SomeHealthCheck构造函数中,并且SomeHealthCheck将作为运行状况检查功能的一部分运行。 / p>

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks();
    services.AddSingleton<SomeDependency>();

    // register the custom health check 
    // after AddHealthChecks and after SomeDependency 
    services.AddSingleton<IHealthCheck, SomeHealthCheck>();
}

更多详细信息

comment in the Health Check samples指出:

  

所有IHealthCheck服务将对健康检查服务和中间件可用。我们建议将所有运行状况检查注册为Singleton服务。

完整样本

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public class SomeDependency
{
    public string GetMessage() => "Hello from SomeDependency";
}

public class SomeHealthCheck : IHealthCheck
{
    public string Name => nameof(SomeHealthCheck);

    private readonly SomeDependency someDependency;

    public SomeHealthCheck(SomeDependency someDependency)
    {
        this.someDependency = someDependency;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var message = this.someDependency.GetMessage();
        var result = new HealthCheckResult(HealthCheckStatus.Failed, null, null, null);
        return Task.FromResult(result);
    }
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
        services.AddSingleton<SomeDependency>();
        services.AddSingleton<IHealthCheck, SomeHealthCheck>();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseHealthChecks("/healthz");
        app.Run(async (context) => await context.Response.WriteAsync("Hello World!"));
    }
}

此示例也是available on GitHub here

答案 1 :(得分:3)

从.NET Core 3.0开始,注册更加简单,并且可以简化为

public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks();
    services.AddSingleton<SomeDependency>();
    services.AddCheck<SomeHealthCheck>("mycheck");
}

请注意,在使用引擎需要使用的内容时,您不再遇到 singleton transient 的冲突。

支票的名称是必填项,因此您必须领一张。

accepted asnwer似乎不再起作用。

答案 2 :(得分:2)

除了Shaun的答案:还有一个open pull-request,它可以将任何生命周期(瞬态和作用域)的服务注入到运行状况检查中。这可能会在2.2版本中发布。

当您可以在运行状况检查中使用临时服务和作用域服务时,应register them using a transient lifestyle

答案 3 :(得分:0)

我在ASP.NET Core 3.1 Web API中为此苦苦挣扎,因为我遵循上述典型的DI方法,方法是:

services.AddHealthChecks();
services.AddSingleton<IHealthCheck, MyHealthCheck1>();    
services.AddSingleton<IHealthCheck, MyHealthCheck2>();

不幸的是,由于未调用IHealthCheck实现,因此在ASP.NET Core 3.1中似乎实际上不起作用。

相反,我必须在Startup.ConfigureServices()中执行以下操作:

services.AddHealthChecks()
    .AddCheck<MyHealthCheck1>("My1-check",
        HealthStatus.Unhealthy,
        new string[] { "tag1" })
    .AddCheck<MyHealthCheck2>("My2-check",
        HealthStatus.Unhealthy,
        new string[] { "tag2" });

然后在Startup.Configure()中,我还按如下方式调用MapHealthChecks():

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapHealthChecks("/hc");
});