簡體   English   中英

如何在 ASP.NET Core 健康檢查中注入依賴項

[英]How to inject dependencies inside an ASP.NET Core Health Check

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

在 .net 博客上的此鏈接中,它顯示了一個示例:

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方法中運行,所以我不能在我的自定義檢查器中注入任何依賴項。

有沒有辦法解決這個問題?

從 .NET Core 3.0 開始,注冊更簡單,歸結為

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

請注意,當您使用引擎需要使用的內容時,您不再有單例瞬態沖突。

支票的名稱是強制性的,因此您必須選擇一張。

雖然接受的 asnwer似乎不再起作用。

簡答

如何在 ASP.NET Core Health Check 中注入依賴項。

如果我們以正確的順序注冊我們的服務,那么SomeDependency將可用於注入SomeHealthCheck構造函數, SomeHealthCheck將作為健康檢查功能的一部分運行。

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

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

更多細節

健康檢查示例中的評論指出:

所有 IHealthCheck 服務都可用於健康檢查服務和中間件。 我們建議將所有健康檢查注冊為單例服務。

完整樣本

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!"));
    }
}

此示例也可在此處的 GitHub 上獲得

除了肖恩的回答:還有一個開放的拉取請求,它允許將任何生命周期(瞬態和范圍)的服務注入健康檢查。 這可能會出現在 2.2 版本中。

當您可以在健康檢查中使用瞬態和范圍服務時,您應該使用瞬態生活方式注冊它們

我在我的 ASP.NET Core 3.1 Web API 中遇到了這個問題,因為我遵循了上面描述的典型 DI 方法,調用:

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

不幸的是,似乎在 ASP.NET Core 3.1 中實際上不起作用,因為我的 IHealthCheck 實現沒有被調用。

相反,我必須在 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");
});

在 asp.net 核心中進行健康檢查的依賴注入的工作方式與通過ServiceProvider添加的任何其他注冊服務的工作方式完全相同。

這意味着將您的健康檢查創建為

public class Foo : IHealthCheck {
    private ILogger<Foo> _log;
    public Foo(ILogger<Foo> log) {
        _log = log; // log is injected through the DI mechanisms
    }
}

並注冊(在這里使用新的 6 樣式):

builder.AddHealthChecks().AddHealthCheck<Foo>();

因此,這也意味着您可以注入IServiceProvider本身並在需要獲取更多所需服務或奇怪的用例時在內部使用它。

我很好奇為什么文檔中沒有明確說明這一點,也沒有這方面的例子,因為它不是“顯而易見的”。 但它顯然遵循了 asp.net 核心領域中一切的經典模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM