ASP.NET Core 中的健康狀態檢查

作者:Glenn CondronJuergen Gutsch

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

ASP.NET Core 提供健康情況檢查中介軟體和程式庫,用來報告應用程式基礎結構元件的健康情況。

應用程式會將健康狀態檢查公開為 HTTP 端點。 您可以針對各種即時監控案例來設定健康情況檢查端點:

  • 容器協調器和負載平衡器可以使用健康狀態探查,來檢查應用程式的狀態。 例如,容器協調器可能會暫停輪流部署或重新啟動容器,來回應失敗的健康狀態檢查。 負載平衡器可能會將流量從失敗的執行個體路由傳送至狀況良好的執行個體,來回應狀況不良的應用程式。
  • 您可以監控所使用記憶體、磁碟及其他實體伺服器資源的健康狀態。
  • 健康狀態檢查可以測試應用程式的相依性 (例如資料庫和外部服務端點),確認其是否可用且正常運作。

健康情況檢查通常會與外部監控服務或容器協調器搭配使用,來檢查應用程式的狀態。 將健康狀態檢查新增至應用程式之前,請決定要使用的監控系統。 監控系統會指定要建立哪些健康狀態檢查類型,以及如何設定其端點。

基本健康狀態探查

對於許多應用程式,報告應用程式是否可處理要求的基本健康狀態探查組態 (「活躍度」),便足以探索應用程式的狀態。

基本設定會登錄健康情況檢查服務,並呼叫健康情況檢查中介軟體以在具有健康情況回應的 URL 端點做出回應。 預設並未登錄特定健康狀態檢查來測試任何特定相依性或子系統。 如果應用程式可以在健康情況端點 URL 做出回應,則視為狀況良好。 預設回應寫入器會將 HealthStatus 以純文字回應形式寫入至用戶端。 HealthStatusHealthStatus.HealthyHealthStatus.DegradedHealthStatus.Unhealthy

Program.cs 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 呼叫 MapHealthChecks 來建立健康情況檢查端點。

下列範例會在 /healthz 建立健康情況檢查端點:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

Docker HEALTHCHECK

Docker 提供內建 HEALTHCHECK 指示詞,可用來檢查使用基本健康狀態檢查組態的應用程式狀態:

HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit

上述範例會使用 curl,以在 /healthz 針對健康情況檢查端點提出 HTTP 要求。 curl 未包括在 .NET Linux 容器映像中,但可以在 Dockerfile 中安裝必要套件來進行新增。 根據 Alpine Linux 來使用映像的容器可以使用所包括的 wget 來取代 curl

建立健康狀態檢查

健康狀態檢查是藉由實作 IHealthCheck 介面來建立。 CheckHealthAsync 方法會傳回指出狀態為 HealthyDegradedUnhealthyHealthCheckResult。 結果會寫成具有可設定狀態碼的純文字回應。 健康情況檢查選項小節中會描述設定。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

下列範例示範健康情況檢查的配置:

public class SampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

健康情況檢查的邏輯放在 CheckHealthAsync 方法中。 上述範例會將虛擬變數 isHealthy 設定為 true。 如果 isHealthy 的值設定為 false,則會傳回 HealthCheckRegistration.FailureStatus 狀態。

如果 CheckHealthAsync 在檢查期間擲回例外狀況,則會傳回其 HealthReportEntry.Status 設定為 FailureStatus 的新 HealthReportEntry。 此狀態是由 AddCheck 所定義 (請參閱登錄健康情況檢查服務一節),並包括造成檢查失敗的內部例外狀況Description 會設定為例外狀況的訊息。

登錄健康狀態檢查服務

若要登錄健康情況檢查服務,請在 Program.cs 中呼叫 AddCheck

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>("Sample");

下列範例中所顯示的 AddCheck 多載會設定在健康狀態檢查報告失敗時所要報告的失敗狀態 (HealthStatus)。 如果將失敗狀態設定為 null (預設),則會報告 HealthStatus.Unhealthy。 此多載對程式庫作者很有用。若健康狀態檢查實作採用此設定,則當健康狀態檢查失敗時,應用程式就會強制程式庫指出失敗狀態。

「標記」可以用來篩選健康情況檢查。 標記會在篩選健康情況檢查小節中予以描述。

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" });

AddCheck 也可以執行匿名函式。 在下列範例中,健康情況檢查一律會傳回狀況良好結果:

builder.Services.AddHealthChecks()
    .AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));

呼叫 AddTypeActivatedCheck,以將引數傳遞至健康情況檢查實作。 在下列範例中,啟用類型的健康情況檢查會在其建構函式中接受整數和字串:

public class SampleHealthCheckWithArgs : IHealthCheck
{
    private readonly int _arg1;
    private readonly string _arg2;

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // ...

        return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
    }
}

若要登錄上述健康情況檢查,請使用傳遞為引數的整數和字串來呼叫 AddTypeActivatedCheck

builder.Services.AddHealthChecks()
    .AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" },
        args: new object[] { 1, "Arg" });

使用健康情況檢查路由傳送

Program.cs 中,使用端點 URL 或相對路徑以在端點建立器上呼叫 MapHealthChecks

app.MapHealthChecks("/healthz");

需要主機

呼叫 RequireHost,以將一或多個允許的主機指定給健康情況檢查端點。 主機應該是 Unicode,而不是 punycode,而且可能會包括連接埠。 如果未提供集合,則會接受任何主機:

app.MapHealthChecks("/healthz")
    .RequireHost("www.contoso.com:5001");

若要限制健康情況檢查端點只在特定連接埠上回應,請在 RequireHost 呼叫中指定連接埠。 此方式通常用於容器環境,以公開監控服務的連接埠:

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001");

警告

依賴於主機標頭的 API (例如 HttpRequest.HostRequireHost) 可能會受到用戶端的詐騙。

若要防止主機和連接埠詐騙,請使用下列其中一種方式:

若要防止未經授權的用戶端詐騙連接埠,請呼叫 RequireAuthorization

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001")
    .RequireAuthorization();

如需詳細資訊,請參閱具有 RequireHost 之路由中的主機比對

需要授權

呼叫 RequireAuthorization,以在健康情況檢查要求端點上執行授權中介軟體。 RequireAuthorization 多載接受一或多個授權原則。 如果未提供原則,則會使用預設授權原則:

app.MapHealthChecks("/healthz")
    .RequireAuthorization();

啟用跨原始來源要求 (CORS)

雖然從瀏覽器手動執行健康情況檢查不是常見案例,但是您可以在健康情況檢查端點上呼叫 RequireCors,以啟用 CORS 中介軟體。 RequireCors 多載接受 CORS 原則建立器委派 (CorsPolicyBuilder) 或原則名稱。 如需詳細資訊,請參閱在 ASP.NET Core 中啟用跨原始來源要求 (CORS)

健康狀態檢查選項

HealthCheckOptions 讓您有機會自訂健康狀態檢查行為:

篩選健康狀態檢查

根據預設,健康情況檢查中介軟體會執行所有已登錄的健康情況檢查。 若要執行健康狀態檢查子集,請對 Predicate 選項提供傳回布林值的函式。

下列範例會篩選健康情況檢查,以只執行已標記 sample 的檢查:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});

自訂 HTTP 狀態碼

您可以使用 ResultStatusCodes 來自訂健康狀態與 HTTP 狀態碼的對應。 下列 StatusCodes 指派是中介軟體所使用的預設值。 變更狀態碼值,以符合您的需求:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResultStatusCodes =
    {
        [HealthStatus.Healthy] = StatusCodes.Status200OK,
        [HealthStatus.Degraded] = StatusCodes.Status200OK,
        [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
    }
});

隱藏快取標頭

AllowCachingResponses 會控制健康情況檢查中介軟體是否將 HTTP 標頭新增至探查回應,以防止回應快取。 如果值為 false (預設),則中介軟體會設定或覆寫 Cache-ControlExpiresPragma 標頭,以防止回應快取。 如果值為 true,則中介軟體不會修改回應的快取標頭:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    AllowCachingResponses = true
});

自訂輸出

若要自訂健康情況檢查報告的輸出,請將 HealthCheckOptions.ResponseWriter 屬性設定為可寫入回應的委派:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResponseWriter = WriteResponse
});

預設委派會使用字串值 HealthReport.Status 寫入基本純文字回應。 下列自訂委派會使用 System.Text.Json 來輸出自訂 JSON 回應:

private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions { Indented = true };

    using var memoryStream = new MemoryStream();
    using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
    {
        jsonWriter.WriteStartObject();
        jsonWriter.WriteString("status", healthReport.Status.ToString());
        jsonWriter.WriteStartObject("results");

        foreach (var healthReportEntry in healthReport.Entries)
        {
            jsonWriter.WriteStartObject(healthReportEntry.Key);
            jsonWriter.WriteString("status",
                healthReportEntry.Value.Status.ToString());
            jsonWriter.WriteString("description",
                healthReportEntry.Value.Description);
            jsonWriter.WriteStartObject("data");

            foreach (var item in healthReportEntry.Value.Data)
            {
                jsonWriter.WritePropertyName(item.Key);

                JsonSerializer.Serialize(jsonWriter, item.Value,
                    item.Value?.GetType() ?? typeof(object));
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WriteEndObject();
        }

        jsonWriter.WriteEndObject();
        jsonWriter.WriteEndObject();
    }

    return context.Response.WriteAsync(
        Encoding.UTF8.GetString(memoryStream.ToArray()));
}

健康情況檢查 API 未提供複雜 JSON 傳回格式的內建支援,因為此格式是您所選擇的監控系統所特有。 視需要,自訂上述範例中的回應。 如需使用 System.Text.Json 進行 JSON 序列化的詳細資訊,請參閱如何在 .NET 中序列化和還原序列化 JSON

資料庫探查

健康狀態檢查可指定資料庫查詢以布林測試方式來執行,藉此指出資料庫是否正常回應。

AspNetCore.Diagnostics.HealthChecks,一種適用於 ASP.NET Core 應用程式的健康情況檢查程式庫,包括針對 SQL Server 資料庫所執行的健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會對資料庫執行 SELECT 1 查詢,以確認資料庫連線狀況良好。

警告

使用查詢檢查資料庫連線時,請選擇快速傳回的查詢。 查詢方法具有多載資料庫而降低其效能的風險。 在大部分情況下,不需要執行測試查詢。 只要成功建立資料庫連線就已足夠。 如果您發現有必要執行查詢,請選擇簡單的 SELECT 查詢,例如 SELECT 1

若要使用此 SQL Server 健康情況檢查,請包括 AspNetCore.HealthChecks.SqlServer NuGet 套件的套件參考。 下列範例會登錄 SQL Server 健康情況檢查:

var conStr = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(conStr))
{
    throw new InvalidOperationException(
                       "Could not find a connection string named 'DefaultConnection'.");
}
builder.Services.AddHealthChecks()
    .AddSqlServer(conStr);

注意

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

Entity Framework Core DbContext 探查

DbContext 檢查會確認應用程式是否可以與針對 EF CoreDbContext 所設定的資料庫通訊。 應用程式支援 DbContext 檢查:

AddDbContextCheck 會登錄 DbContext 的健康狀態檢查。 DbContext 會以 TContext 形式提供給方法。 多載可用來設定失敗狀態、標籤和自訂測試查詢。

預設情況:

  • DbContextHealthCheck 會呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態時所要執行的作業。
  • 健康狀態檢查的名稱是 TContext 類型的名稱。

下列範例會登錄 DbContext 和相關聯的 DbContextHealthCheck

builder.Services.AddDbContext<SampleDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddHealthChecks()
    .AddDbContextCheck<SampleDbContext>();

個別的整備度與活躍度探查

在某些裝載案例中,會使用一組健康情況檢查來區分兩個應用程式狀態:

  • 「整備」指出應用程式是否正在正常執行,但尚未準備好接收要求。
  • 「活躍度」指出應用程式是否已當機,而且必須重新予以啟動。

請考慮下列範例:應用程式在準備好處理要求之前必須下載大型設定檔。 如果初始下載失敗,則我們不想要重新啟動應用程式,因為應用程式可以重試下載檔案數次。 我們使用「活躍度探查」來描述處理序的活躍度,而不會執行其他檢查。 我們也想要防止在設定檔下載成功之前將要求傳送至應用程式。 除非下載成功,而且應用程式準備好接收要求,否則我們會使用「整備度探查」來指出「尚未就緒」狀態。

下列背景工作會模擬大約需要 15 秒的啟動處理序。 完成後,工作會將 StartupHealthCheck.StartupCompleted 屬性設定為 True:

public class StartupBackgroundService : BackgroundService
{
    private readonly StartupHealthCheck _healthCheck;

    public StartupBackgroundService(StartupHealthCheck healthCheck)
        => _healthCheck = healthCheck;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Simulate the effect of a long-running task.
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _healthCheck.StartupCompleted = true;
    }
}

StartupHealthCheck 會報告長時間執行的啟動工作完成,並公開背景服務所設定的 StartupCompleted 屬性:

public class StartupHealthCheck : IHealthCheck
{
    private volatile bool _isReady;

    public bool StartupCompleted
    {
        get => _isReady;
        set => _isReady = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        if (StartupCompleted)
        {
            return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
        }

        return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
    }
}

健康狀態檢查是 Program.cs 中使用 AddCheck 隨託管服務一起登錄。 因為所裝載服務必須在健康情況檢查上設定此屬性,所以也會在服務容器中將健康情況檢查登錄為單一資料庫:

builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();

builder.Services.AddHealthChecks()
    .AddCheck<StartupHealthCheck>(
        "Startup",
        tags: new[] { "ready" });

若要建立兩個不同的健康情況檢查端點,請呼叫 MapHealthChecks 兩次:

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});

app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
    Predicate = _ => false
});

上述範例會建立下列健康情況檢查端點:

  • /healthz/ready 用於整備檢查。 整備檢查會將健康情況檢查篩選為已標記 ready 的檢查。
  • /healthz/live 用於活躍度檢查。 活躍度檢查會在 HealthCheckOptions.Predicate 委派中傳回 false,以篩選出所有健康情況檢查。 如需篩選健康情況檢查的詳細資訊,請參閱本文中的篩選健康情況檢查

啟動工作完成之前,/healthz/ready 端點會回報 Unhealthy 狀態。 啟動工作完成之後,此端點會回報 Healthy 狀態。 /healthz/live 端點會排除所有檢查,並將所有呼叫的狀態都回報為 Healthy

Kubernetes 範例

使用個別的整備度與活躍度檢查在 Kubernetes 之類的環境中很有用。 在 Kubernetes 中,應用程式可能需要先執行耗時的啟動工作,才能接受要求 (例如基礎資料庫可用性測試)。 使用個別的檢查可讓協調器區分應用程式是否為正常運作但尚未準備好,或應用程式是否無法啟動。 如需 Kubernetes 中整備度與活躍度探查的詳細資訊,請參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設定活躍度與整備度探查)。

下列範例示範 Kubernetes 整備度探查組態:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /healthz/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

發佈健康狀態檢查程式庫

若要發佈健康狀態檢查作為程式庫:

  1. 寫入健康狀態檢查,將 IHealthCheck 介面當做獨立類別來實作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項來存取組態資料。

  2. 使用取用應用程式在其 Program.cs 方法中呼叫的參數,來寫入延伸模組。 請考慮下列範例健康情況檢查,而此檢查接受 arg1arg2 作為建構函式參數:

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);
    

    上述簽章指出健康情況檢查需要自訂資料,才能處理健康情況檢查探查邏輯。 此資料會提供給委派,以在使用延伸模組登錄健康狀態檢查時,用來建立健康狀態檢查執行個體。 在下列範例中,呼叫端會指定:

    • arg1:健康情況檢查的整數資料點。
    • arg2:健康情況檢查的字串引數。
    • name:選用的健康情況檢查名稱。 如果 null,則會使用預設值。
    • failureStatus:選用的 HealthStatus,其回報失敗狀態。 如果為 null,則會使用 HealthStatus.Unhealthy
    • tags:標記的選用 IEnumerable<string> 集合。
    public static class SampleHealthCheckBuilderExtensions
    {
        private const string DefaultName = "Sample";
    
        public static IHealthChecksBuilder AddSampleHealthCheck(
            this IHealthChecksBuilder healthChecksBuilder,
            int arg1,
            string arg2,
            string? name = null,
            HealthStatus? failureStatus = null,
            IEnumerable<string>? tags = default)
        {
            return healthChecksBuilder.Add(
                new HealthCheckRegistration(
                    name ?? DefaultName,
                    _ => new SampleHealthCheckWithArgs(arg1, arg2),
                    failureStatus,
                    tags));
        }
    }
    

健康狀態檢查發行者

IHealthCheckPublisher 新增至服務容器時,健康狀態檢查系統會定期執行健康狀態檢查,並呼叫 PublishAsync 傳回結果。 此處理序適用於推送型健康情況監控系統案例,而此案例預期每個處理序都會定期呼叫監控系統來判斷健康情況。

HealthCheckPublisherOptions 可讓您設定:

  • Delay:初始延遲會在應用程式啟動之後且執行 IHealthCheckPublisher 執行個體之前套用。 啟動後就會套用延遲,但不會套用至後面的反覆項目。 預設值是五秒鐘。
  • PeriodIHealthCheckPublisher 執行的期間。 預設值為 30 秒。
  • Predicate:如果 Predicatenull (預設),則健康情況檢查發行者服務會執行所有已登錄的健康情況檢查。 若要執行一部分的健康狀態檢查,請提供可篩選該組檢查的函式。 每個期間都會評估該述詞。
  • Timeout:執行所有 IHealthCheckPublisher 執行個體之健康情況檢查的逾時。 若要在沒有逾時的情況下執行,請使用 InfiniteTimeSpan。 預設值為 30 秒。

下列範例示範健康情況發行者的配置:

public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            // ...
        }
        else
        {
            // ...
        }

        return Task.CompletedTask;
    }
}

HealthCheckPublisherOptions 類別提供屬性來設定健康情況檢查發行者的行為。

下列範例會將健康情況檢查發行者登錄為單一資料庫,並設定 HealthCheckPublisherOptions

builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});

builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();

AspNetCore.Diagnostics.HealthChecks

  • 包括數個系統的發行者,包括 Application Insights
  • 受 Microsoft 維護或支援。

個別的 HealthChecks

DelayPeriod 可以在每個 HealthCheckRegistration 上個別設定。 當您想要以與 HealthCheckPublisherOptions 中所設定的期間不同的速率執行一些健康情況檢查時,這非常有用。

下列程式碼會設定 SampleHealthCheck1DelayPeriod

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks()
   .Add(new HealthCheckRegistration(
       name: "SampleHealthCheck1",
       instance: new SampleHealthCheck(),
       failureStatus: null,
       tags: null,
       timeout: default)
   {
       Delay = TimeSpan.FromSeconds(40),
       Period = TimeSpan.FromSeconds(30)
   });

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

相依性插入和健康情況檢查

您可以使用相依性插入來取用健康情況檢查類別內特定 Type 的執行個體。 相依性插入適用於將選項或全域設定插入至健康情況檢查。 使用相依性插入「不」是設定健康情況檢查的常見案例。 通常,每個健康情況檢查都是專屬於實際測試,並且使用 IHealthChecksBuilder 擴充方法進行設定。

下列範例顯示可透過相依性插入來擷取設定物件的範例健康情況檢查:

public class SampleHealthCheckWithDI : IHealthCheck
{
    private readonly SampleHealthCheckWithDiConfig _config;

    public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
        => _config = config;

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // use _config ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

SampleHealthCheckWithDiConfig 和健康情況檢查需要新增至服務容器:

builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
    BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheckWithDI>(
        "With Dependency Injection",
        tags: new[] { "inject" });

UseHealthChecks 與MapHealthChecks

有兩種方式可讓呼叫端存取健康情況檢查:

  • UseHealthChecks 會登錄中介軟體來處理中介軟體管線中的健康情況檢查要求。
  • MapHealthChecks 會登錄健康情況檢查端點。 端點會與應用程式中的其他端點進行比對和執行。

使用 MapHealthChecks 優於 UseHealthChecks 的優點是能夠使用端點感知中介軟體 (例如授權),並更精細地控制比對原則。 使用 UseHealthChecks 優於 MapHealthChecks 的主要優點是確切控制中介軟體管線中執行健康情況檢查的位置。

UseHealthChecks

  • 在要求符合健康情況檢查端點時終止管線。 最短線路可避免不必要的工作,因此經常使用 (例如記錄和其他中介軟體)。
  • 主要用於在管線中設定健康情況檢查中介軟體。
  • 可以比對連接埠上的任何路徑與 null 或空白 PathString。 允許在針對所指定連接埠所提出的任何要求上執行健康情況檢查。
  • 原始程式碼

MapHealthChecks 允許:

  • 呼叫 ShortCircuit,以在要求符合健康情況檢查端點時終止管線。 例如: app.MapHealthChecks("/healthz").ShortCircuit(); 。 如需詳細資訊,請參閱路由之後尋找中介軟體的最短路徑
  • 對應特定路由或端點以進行健康情況檢查。
  • 自訂可存取健康情況檢查端點的 URL 或路徑。
  • 使用不同的路由或設定來對應多個健康情況檢查端點。 多個端點支援:
    • 針對不同類型的健康情況檢查或元件啟用不同的端點。
    • 用來區分應用程式健康情況的不同層面,或將特定設定套用至健康情況檢查的子集。
  • 原始程式碼

其他資源

注意

本文部分是透過人工智慧協助建立的。 發佈之前,請視需要進行作者檢閱並修訂內容。 請參閱我們在 Microsoft Learn 中使用 AI 產生的內容的原則

ASP.NET Core 提供健康情況檢查中介軟體和程式庫,用來報告應用程式基礎結構元件的健康情況。

應用程式會將健康狀態檢查公開為 HTTP 端點。 您可以針對各種即時監控案例來設定健康情況檢查端點:

  • 容器協調器和負載平衡器可以使用健康狀態探查,來檢查應用程式的狀態。 例如,容器協調器可能會暫停輪流部署或重新啟動容器,來回應失敗的健康狀態檢查。 負載平衡器可能會將流量從失敗的執行個體路由傳送至狀況良好的執行個體,來回應狀況不良的應用程式。
  • 您可以監控所使用記憶體、磁碟及其他實體伺服器資源的健康狀態。
  • 健康狀態檢查可以測試應用程式的相依性 (例如資料庫和外部服務端點),確認其是否可用且正常運作。

檢視或下載範例程式碼 \(英文\) (如何下載)

範例應用程式包括本文中所述的案例範例。 若要在指定的案例中執行範例應用程式,請在命令殼層中使用來自專案資料夾的 dotnet run 命令。 如需如何使用範例應用程式的詳細資料,請參閱範例應用程式的 README.md 檔案和本文中的案例描述。

必要條件

健康情況檢查通常會與外部監控服務或容器協調器搭配使用,來檢查應用程式的狀態。 將健康狀態檢查新增至應用程式之前,請決定要使用的監控系統。 監控系統會指定要建立哪些健康狀態檢查類型,以及如何設定其端點。

ASP.NET Core 應用程式會隱含參考 Microsoft.AspNetCore.Diagnostics.HealthChecks 套件。 若要使用 Entity Framework Core 來執行健康情況檢查,請新增 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 套件的參考。

範例應用程式提供啟動程式碼,來示範數個案例的健康狀態檢查。 資料庫探查案例使用 AspNetCore.Diagnostics.HealthChecks 來檢查資料庫連線的健康情況。 DbContext 探查案例使用 EF CoreDbContext 來檢查資料庫。 為了探索資料庫案例,範例應用程式會:

注意

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

另一個健康狀態檢查案例示範如何將健康狀態檢查篩選至管理連接埠。 範例應用程式需要您建立 Properties/launchSettings.json 檔案,而此檔案包括管理 URL 和管理連接埠。 如需詳細資訊,請參閱依連接埠篩選一節。

基本健康狀態探查

對於許多應用程式,報告應用程式是否可處理要求的基本健康狀態探查組態 (「活躍度」),便足以探索應用程式的狀態。

基本設定會登錄健康情況檢查服務,並呼叫健康情況檢查中介軟體以在具有健康情況回應的 URL 端點做出回應。 預設並未登錄特定健康狀態檢查來測試任何特定相依性或子系統。 如果應用程式可以在健康情況端點 URL 做出回應,則視為狀況良好。 預設回應寫入器會將狀態 (HealthStatus) 以純文字回應形式回寫至用戶端,指出 HealthStatus.HealthyHealthStatus.DegradedHealthStatus.Unhealthy 狀態。

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點。

在範例應用程式中,是在 /health (BasicStartup.cs) 建立健康情況檢查端點:

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

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

若要使用範例應用程式執行基本組態案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario basic

Docker 範例

Docker 提供內建 HEALTHCHECK 指示詞,可用來檢查使用基本健康狀態檢查組態的應用程式狀態:

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

建立健康狀態檢查

健康狀態檢查是藉由實作 IHealthCheck 介面來建立。 CheckHealthAsync 方法會傳回指出狀態為 HealthyDegradedUnhealthyHealthCheckResult。 結果會寫成具有可設定狀態碼的純文字回應 (健康狀態檢查選項一節中將說明如何進行組態)。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

下列 ExampleHealthCheck 類別示範健康情況檢查的配置。 健康情況檢查邏輯放在 CheckHealthAsync 方法中。 下列範例會將虛擬變數 healthCheckResultHealthy 設定為 true。 如果 healthCheckResultHealthy 的值設定為 false,則會傳回 HealthCheckRegistration.FailureStatus 狀態。

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(context.Registration.FailureStatus, 
            "An unhealthy result."));
    }
}

如果 CheckHealthAsync 在檢查期間擲回例外狀況,則會傳回其 HealthReportEntry.Status 設定為 FailureStatus 的新 HealthReportEntry (這由 AddCheck 所定義) (請參閱登錄健康情況檢查服務小節),並包括最初造成檢查失敗的內部例外狀況Description 會設定為例外狀況的訊息。

登錄健康狀態檢查服務

Startup.ConfigureServices 中使用 AddCheck,以將 ExampleHealthCheck 類型新增至健康情況檢查服務:

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

下列範例中所顯示的 AddCheck 多載會設定在健康狀態檢查報告失敗時所要報告的失敗狀態 (HealthStatus)。 如果將失敗狀態設定為 null (預設),則會報告 HealthStatus.Unhealthy。 此多載對程式庫作者很有用。若健康狀態檢查實作採用此設定,則當健康狀態檢查失敗時,應用程式就會強制程式庫指出失敗狀態。

您可以使用「標籤」來篩選健康狀態檢查 (篩選健康狀態檢查一節中將進一步說明)。

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck 也可以執行匿名函式。 在下列範例中,健康狀態檢查名稱指定為 Example,且檢查一律會傳回狀況良好狀態:

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

呼叫 AddTypeActivatedCheck,以將引數傳遞至健康情況檢查實作。 在下列範例中,TestHealthCheckWithArgs 接受在呼叫 CheckHealthAsync 時使用整數和字串:

private class TestHealthCheckWithArgs : IHealthCheck
{
    public TestHealthCheckWithArgs(int i, string s)
    {
        I = i;
        S = s;
    }

    public int I { get; set; }

    public string S { get; set; }

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

使用傳遞至實作的整數和字串來呼叫 AddTypeActivatedCheck,以登錄 TestHealthCheckWithArgs

services.AddHealthChecks()
    .AddTypeActivatedCheck<TestHealthCheckWithArgs>(
        "test", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "example" }, 
        args: new object[] { 5, "string" });

使用健康情況檢查路由傳送

Startup.Configure 中,使用端點 URL 或相對路徑以在端點建立器上呼叫 MapHealthChecks

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

需要主機

呼叫 RequireHost,以將一或多個允許的主機指定給健康情況檢查端點。 主機應該是 Unicode,而不是 punycode,而且可能會包括連接埠。 如果未提供集合,則會接受任何主機。

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});

如需詳細資訊,請參閱依連接埠篩選一節。

需要授權

呼叫 RequireAuthorization,以在健康情況檢查要求端點上執行授權中介軟體。 RequireAuthorization 多載接受一或多個授權原則。 如果未提供原則,則會使用預設授權原則。

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireAuthorization();
});

啟用跨原始來源要求 (CORS)

雖然從瀏覽器手動執行健康情況檢查不是常見使用案例,但是您可以在健康情況檢查端點上呼叫 RequireCors,以啟用 CORS 中介軟體。 RequireCors 多載接受 CORS 原則建立器委派 (CorsPolicyBuilder) 或原則名稱。 如果未提供原則,則會使用預設 CORS 原則。 如需詳細資訊,請參閱在 ASP.NET Core 中啟用跨原始來源要求 (CORS)

健康狀態檢查選項

HealthCheckOptions 讓您有機會自訂健康狀態檢查行為:

篩選健康狀態檢查

根據預設,健康情況檢查中介軟體會執行所有已登錄的健康情況檢查。 若要執行健康狀態檢查子集,請對 Predicate 選項提供傳回布林值的函式。 在下列範例中,會依函式條件陳述式中的標籤 (bar_tag) 篩選出 Bar 健康狀態檢查。只有在健康狀態檢查的 Tags 屬性符合 foo_tagbaz_tag 時,才傳回 true

Startup.ConfigureServices 中:

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });

Startup.Configure 中,Predicate 會篩選出「橫條圖」健康情況檢查。 只有 Foo 和 Baz 才能執行:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
});

自訂 HTTP 狀態碼

您可以使用 ResultStatusCodes 來自訂健康狀態與 HTTP 狀態碼的對應。 下列 StatusCodes 指派是中介軟體所使用的預設值。 請變更狀態碼值以符合您的需求。

Startup.Configure 中:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        }
    });
});

隱藏快取標頭

AllowCachingResponses 會控制健康情況檢查中介軟體是否將 HTTP 標頭新增至探查回應,以防止回應快取。 如果值為 false (預設),則中介軟體會設定或覆寫 Cache-ControlExpiresPragma 標頭,以防止回應快取。 如果值為 true,則中介軟體不會修改回應的快取標頭。

Startup.Configure 中:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        AllowCachingResponses = true
    });
});

自訂輸出

Startup.Configure 中,將 HealthCheckOptions.ResponseWriter 選項設定為撰寫回應的委派:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
});

預設委派會使用字串值 HealthReport.Status 寫入基本純文字回應。 下列自訂委派會輸出自訂 JSON 回應。

範例應用程式中的第一個範例示範如何使用 System.Text.Json

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions
    {
        Indented = true
    };

    using (var stream = new MemoryStream())
    {
        using (var writer = new Utf8JsonWriter(stream, options))
        {
            writer.WriteStartObject();
            writer.WriteString("status", result.Status.ToString());
            writer.WriteStartObject("results");
            foreach (var entry in result.Entries)
            {
                writer.WriteStartObject(entry.Key);
                writer.WriteString("status", entry.Value.Status.ToString());
                writer.WriteString("description", entry.Value.Description);
                writer.WriteStartObject("data");
                foreach (var item in entry.Value.Data)
                {
                    writer.WritePropertyName(item.Key);
                    JsonSerializer.Serialize(
                        writer, item.Value, item.Value?.GetType() ??
                        typeof(object));
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }

        var json = Encoding.UTF8.GetString(stream.ToArray());

        return context.Response.WriteAsync(json);
    }
}

第二個範例示範如何使用 Newtonsoft.Json

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

在範例應用程式中,註解化 CustomWriterStartup.cs 中的 SYSTEM_TEXT_JSON前置處理器指示詞,以啟用 WriteResponseNewtonsoft.Json 版本。

健康情況檢查 API 未提供複雜 JSON 傳回格式的內建支援,因為此格式是您所選擇的監控系統所特有。 視需要,自訂上述範例中的回應。 如需使用 System.Text.Json 進行 JSON 序列化的詳細資訊,請參閱如何在 .NET 中序列化和還原序列化 JSON

資料庫探查

健康狀態檢查可指定資料庫查詢以布林測試方式來執行,藉此指出資料庫是否正常回應。

範例應用程式使用 AspNetCore.Diagnostics.HealthChecks (一種適用於 ASP.NET Core 應用程式的健康情況檢查程式庫),以在 SQL Server 資料庫上執行健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會對資料庫執行 SELECT 1 查詢,以確認資料庫連線狀況良好。

警告

使用查詢檢查資料庫連線時,請選擇快速傳回的查詢。 查詢方法具有多載資料庫而降低其效能的風險。 在大部分情況下,不需要執行測試查詢。 只要成功建立資料庫連線就已足夠。 如果您發現有必要執行查詢,請選擇簡單的 SELECT 查詢,例如 SELECT 1

包括 AspNetCore.HealthChecks.SqlServer 的套件參考。

在範例應用程式的 appsettings.json 檔案中,提供有效的資料庫連接字串。 應用程式使用名為 HealthCheckSample 的 SQL Server 資料庫:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  },
  "AllowedHosts": "*"
}

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 範例應用程式會使用資料庫連接字串 (DbHealthStartup.cs) 來呼叫 AddSqlServer 方法:

services.AddHealthChecks()
    .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks

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

若要使用範例應用程式執行資料庫探查案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario db

注意

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

Entity Framework Core DbContext 探查

DbContext 檢查會確認應用程式是否可以與針對 EF CoreDbContext 所設定的資料庫通訊。 應用程式支援 DbContext 檢查:

AddDbContextCheck<TContext> 會登錄 DbContext 的健康狀態檢查。 DbContext 會以 TContext 形式提供給方法。 多載可用來設定失敗狀態、標籤和自訂測試查詢。

預設情況:

  • DbContextHealthCheck 會呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態時所要執行的作業。
  • 健康狀態檢查的名稱是 TContext 類型的名稱。

在範例應用程式中,會將 AppDbContext 提供給 AddDbContextCheck,並在 Startup.ConfigureServices 中登錄為服務 (DbContextHealthStartup.cs):

services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(
        Configuration["ConnectionStrings:DefaultConnection"]);
});

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks

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

若要使用範例應用程式來執行 DbContext 探查案例,請確認 SQL Server 執行個體中沒有連接字串所指定的資料庫。 如果資料庫存在,請予以刪除。

在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario dbcontext

在應用程式執行之後,對瀏覽器中的 /health 端點提出要求來檢查健康狀態。 資料庫和 AppDbContext 不存在,因此應用程式會提供下列回應:

Unhealthy

觸發範例應用程式以建立資料庫。 對 /createdatabase 提出要求。 應用程式會回應:

Creating the database...
Done!
Navigate to /health to see the health status.

/health 端點提出要求。 資料庫和內容存在,因此應用程式會回應:

Healthy

觸發範例應用程式以刪除資料庫。 對 /deletedatabase 提出要求。 應用程式會回應:

Deleting the database...
Done!
Navigate to /health to see the health status.

/health 端點提出要求。 應用程式會提供狀況不良回應:

Unhealthy

個別的整備度與活躍度探查

在某些裝載案例中,會使用一組健康情況檢查來區分兩個應用程式狀態:

  • 「整備」指出應用程式是否正在正常執行,但尚未準備好接收要求。
  • 「活躍度」指出應用程式是否已當機,而且必須重新予以啟動。

請考慮下列範例:應用程式在準備好處理要求之前必須下載大型設定檔。 如果初始下載失敗,則我們不想要重新啟動應用程式,因為應用程式可以重試下載檔案數次。 我們使用「活躍度探查」來描述處理序的活躍度,而不會執行其他檢查。 我們也想要防止在設定檔下載成功之前將要求傳送至應用程式。 除非下載成功,而且應用程式準備好接收要求,否則我們會使用「整備度探查」來指出「尚未就緒」狀態。

範例應用程式包含健康狀態檢查,會在託管服務中長時間執行的啟動工作完成時回報。 StartupHostedServiceHealthCheck 會公開 StartupTaskCompleted 屬性,而裝載的服務可以在其長時間執行的工作完成時,將此屬性設定為 true (StartupHostedServiceHealthCheck.cs):

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

裝載的服務 (Services/StartupHostedService) 會啟動長時間執行的背景工作。 工作完成時,StartupHostedServiceHealthCheck.StartupTaskCompleted 會設定為 true

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger,
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

健康狀態檢查是 Startup.ConfigureServices 中使用 AddCheck 隨託管服務一起登錄。 因為所裝載服務必須在健康情況檢查上設定此屬性,所以也會在服務容器中登錄健康情況檢查 (LivenessProbeStartup.cs):

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 在範例應用程式中,是在下列位置建立健康情況檢查端點:

  • /health/ready 用於整備檢查。 整備度檢查使用 ready 標籤來篩選健康狀態檢查。
  • /health/live 用於活躍度檢查。 活躍度檢查是在 HealthCheckOptions.Predicate 中傳回 false 來篩選出 StartupHostedServiceHealthCheck (如需詳細資訊,請參閱篩選健康情況檢查)

在下列範例程式碼中:

  • 整備檢查會使用具有「就緒」標記的所有已登錄檢查。
  • Predicate 會排除所有檢查,並傳回 200-Ok。
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

若要使用範例應用程式執行整備度/活躍度組態案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario liveness

在瀏覽器中,瀏覽 /health/ready 數次,直到經過 15 秒。 健康狀態檢查報告前 15 秒為 Unhealthy。 15 秒之後,端點會報告 Healthy,以反映託管服務長時間執行的工作已完成。

此範例也會建立一個以兩秒延遲執行第一次整備檢查的「健康情況檢查發行者」(IHealthCheckPublisher 實作)。 如需詳細資訊,請參閱健康狀態檢查發行者一節。

Kubernetes 範例

使用個別的整備度與活躍度檢查在 Kubernetes 之類的環境中很有用。 在 Kubernetes 中,應用程式可能需要先執行耗時的啟動工作,才能接受要求 (例如基礎資料庫可用性測試)。 使用個別的檢查可讓協調器區分應用程式是否為正常運作但尚未準備好,或應用程式是否無法啟動。 如需 Kubernetes 中整備度與活躍度探查的詳細資訊,請參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設定活躍度與整備度探查)。

下列範例示範 Kubernetes 整備度探查組態:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

透過自訂回應寫入器的計量型探查

範例應用程式示範透過自訂回應寫入器的記憶體健康狀態檢查。

如果應用程式使用超過指定的記憶體閾值 (在範例應用程式中為 1 GB),MemoryHealthCheck 會報告降級的狀態。 HealthCheckResult 包括應用程式的記憶體回收行程 (GC) 資訊 (MemoryHealthCheck.cs):

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
        var status = (allocated < options.Threshold) ?
            HealthStatus.Healthy : context.Registration.FailureStatus;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 MemoryHealthCheck 會登錄為服務,而不是將健康狀態檢查傳遞至 AddCheck 以啟用檢查。 所有 IHealthCheck 登錄的服務都可供健康狀態檢查服務和中介軟體使用。 建議將健康狀態檢查服務登錄為單一服務。

在範例應用程式的 CustomWriterStartup.cs 中:

services.AddHealthChecks()
    .AddMemoryHealthCheck("memory");

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 健康情況檢查執行時,會將 WriteResponse 委派提供給 ResponseWriter 屬性以輸出自訂 JSON 回應:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
}

WriteResponse 委派會將 CompositeHealthCheckResult 格式化為 JSON 物件,並產生健康情況檢查回應的 JSON 輸出。 如需詳細資訊,請參閱自訂輸出小節。

若要使用範例應用程式透過自訂回應寫入器輸出執行計量型探查,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario writer

注意

AspNetCore.Diagnostics.HealthChecks 包括計量型健康情況檢查案例,包括磁碟儲存體和最大值活躍度檢查。

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

依連接埠篩選

使用 URL 模式以在 MapHealthChecks 上呼叫 RequireHost,而此模式指定連接埠來限制針對所指定連接埠的健康情況檢查要求。 此方式通常用於容器環境,以公開監控服務的連接埠。

範例應用程式使用環境變數組態提供者來設定連接埠。 連接埠是在 launchSettings.json 檔案中設定,並透過環境變數傳遞至設定提供者。 您也必須將伺服器設定為在管理連接埠上接聽要求。

若要使用範例應用程式來示範管理連接埠設定,請在 Properties 資料夾中建立 launchSettings.json 檔案。

範例應用程式中的下列 Properties/launchSettings.json 檔案未包括在範例應用程式的專案檔中,而且必須手動予以建立:

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點。

在範例應用程式中,對 Startup.Configure 中端點的 RequireHost 呼叫指定設定管理連接埠:

endpoints.MapHealthChecks("/health")
    .RequireHost($"*:{Configuration["ManagementPort"]}");

在範例應用程式的 Startup.Configure 中,建立端點。 在下列範例程式碼中:

  • 整備檢查會使用具有「就緒」標記的所有已登錄檢查。
  • Predicate 會排除所有檢查,並傳回 200-Ok。
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

注意

您可以在程式碼中明確設定管理連接埠,以避免在範例應用程式中建立 launchSettings.json 檔案。 在 HostBuilder 建立所在的 Program.cs 中,新增 ListenAnyIP 呼叫,並提供應用程式的管理連接埠端點。 在 ManagementPortStartup.csConfigure 中,使用 RequireHost 來指定管理連接埠:

Program.cs

return new HostBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel()
            .ConfigureKestrel(serverOptions =>
            {
                serverOptions.ListenAnyIP(5001);
            })
            .UseStartup(startupType);
    })
    .Build();

ManagementPortStartup.cs

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});

若要使用範例應用程式執行管理連接埠組態案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario port

發佈健康狀態檢查程式庫

若要發佈健康狀態檢查作為程式庫:

  1. 寫入健康狀態檢查,將 IHealthCheck 介面當做獨立類別來實作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項來存取組態資料。

    CheckHealthAsync 的健全狀況檢查邏輯中:

    • data1data2 用於此方法,以執行探查的健康情況檢查邏輯。
    • 已處理 AccessViolationException

    發生 AccessViolationException 時,會使用 HealthCheckResult 來傳回 FailureStatus,以允許使用者設定健康情況檢查失敗狀態。

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    namespace SampleApp
    {
        public class ExampleHealthCheck : IHealthCheck
        {
            private readonly string _data1;
            private readonly int? _data2;
    
            public ExampleHealthCheck(string data1, int? data2)
            {
                _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
                _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
            }
    
            public async Task<HealthCheckResult> CheckHealthAsync(
                HealthCheckContext context, CancellationToken cancellationToken)
            {
                try
                {
                    return HealthCheckResult.Healthy();
                }
                catch (AccessViolationException ex)
                {
                    return new HealthCheckResult(
                        context.Registration.FailureStatus,
                        description: "An access violation occurred during the check.",
                        exception: ex,
                        data: null);
                }
            }
        }
    }
    
  2. 使用取用應用程式在其 Startup.Configure 方法中呼叫的參數,來寫入延伸模組。 在下列範例中,假設健康狀態檢查方法簽章如下:

    ExampleHealthCheck(string, string, int )
    

    上述簽章指出 ExampleHealthCheck 需要額外的資料,才能處理健康狀態檢查探查邏輯。 此資料會提供給委派,以在使用延伸模組登錄健康狀態檢查時,用來建立健康狀態檢查執行個體。 在下列範例中,呼叫者會選擇性地指定:

    • 健康狀態檢查名稱 (name)。 如果為 null,則會使用 example_health_check
    • 健康狀態檢查的字串資料點 (data1)。
    • 健康狀態檢查的整數資料點 (data2)。 如果為 null,則會使用 1
    • 失敗狀態 (HealthStatus)。 預設值為 null。 如果為 null,則會報告失敗狀態為 HealthStatus.Unhealthy
    • 標籤 (IEnumerable<string>)。
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

健康狀態檢查發行者

IHealthCheckPublisher 新增至服務容器時,健康狀態檢查系統會定期執行健康狀態檢查,並呼叫 PublishAsync 傳回結果。 這對推送型健康狀態監控系統案例很有用,其預期每個處理序會定期呼叫監控系統來判斷健康狀態。

IHealthCheckPublisher 介面有單一方法:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions 可讓您設定:

  • Delay:初始延遲會在應用程式啟動之後且執行 IHealthCheckPublisher 執行個體之前套用。 在啟動後就會套用延遲,但不會套用至後續的反覆項目。 預設值是五秒鐘。
  • PeriodIHealthCheckPublisher 執行的期間。 預設值為 30 秒。
  • Predicate:如果 Predicatenull (預設),則健康情況檢查發行者服務會執行所有已登錄的健康情況檢查。 若要執行一部分的健康狀態檢查,請提供可篩選該組檢查的函式。 每個期間都會評估該述詞。
  • Timeout:執行所有 IHealthCheckPublisher 執行個體之健康情況檢查的逾時。 若要在沒有逾時的情況下執行,請使用 InfiniteTimeSpan。 預設值為 30 秒。

在範例應用程式中,ReadinessPublisher 是一個 IHealthCheckPublisher 實作。 在下列記錄層級,會記錄每個檢查的健康情況檢查狀態:

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks
    // Middleware already logs health checks results. A real-world readiness
    // check in a production app might perform a set of more expensive or
    // time-consuming checks to determine if other resources are responding
    // properly.
    public Task PublishAsync(HealthReport report,
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

在範例應用程式的 LivenessProbeStartup 範例中,StartupHostedService 整備檢查具有 2 秒的啟動延遲,且每 30 秒會執行一次檢查。 為了啟用 IHealthCheckPublisher 實作,此範例會在相依性插入 (DI) 容器中將 ReadinessPublisher 註冊為單一服務:

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

注意

AspNetCore.Diagnostics.HealthChecks 包括數個系統的發行者,包括 Application Insights

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

利用 MapWhen 限制健康情況檢查

使用 MapWhen 來有條件地將健康情況檢查端點的要求管線分支。

在下列範例中,如果接收到 api/HealthCheck 端點的 GET 要求,則 MapWhen 會對要求管線進行分支處理,以啟用健康情況檢查中介軟體:

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});

如需詳細資訊,請參閱 ASP.NET Core 中介軟體

ASP.NET Core 提供健康情況檢查中介軟體和程式庫,用來報告應用程式基礎結構元件的健康情況。

應用程式會將健康狀態檢查公開為 HTTP 端點。 您可以針對各種即時監控案例來設定健康情況檢查端點:

  • 容器協調器和負載平衡器可以使用健康狀態探查,來檢查應用程式的狀態。 例如,容器協調器可能會暫停輪流部署或重新啟動容器,來回應失敗的健康狀態檢查。 負載平衡器可能會將流量從失敗的執行個體路由傳送至狀況良好的執行個體,來回應狀況不良的應用程式。
  • 您可以監控所使用記憶體、磁碟及其他實體伺服器資源的健康狀態。
  • 健康狀態檢查可以測試應用程式的相依性 (例如資料庫和外部服務端點),確認其是否可用且正常運作。

檢視或下載範例程式碼 \(英文\) (如何下載)

範例應用程式包括本文中所述的案例範例。 若要在指定的案例中執行範例應用程式,請在命令殼層中使用來自專案資料夾的 dotnet run 命令。 如需如何使用範例應用程式的詳細資料,請參閱範例應用程式的 README.md 檔案和本文中的案例描述。

必要條件

健康情況檢查通常會與外部監控服務或容器協調器搭配使用,來檢查應用程式的狀態。 將健康狀態檢查新增至應用程式之前,請決定要使用的監控系統。 監控系統會指定要建立哪些健康狀態檢查類型,以及如何設定其端點。

ASP.NET Core 應用程式會隱含參考 Microsoft.AspNetCore.Diagnostics.HealthChecks 套件。 若要使用 Entity Framework Core 來執行健康情況檢查,請新增 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 套件的套件參考。

範例應用程式提供啟動程式碼,來示範數個案例的健康狀態檢查。 資料庫探查案例使用 AspNetCore.Diagnostics.HealthChecks 來檢查資料庫連線的健康情況。 DbContext 探查案例使用 EF CoreDbContext 來檢查資料庫。 為了探索資料庫案例,範例應用程式會:

注意

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

另一個健康狀態檢查案例示範如何將健康狀態檢查篩選至管理連接埠。 範例應用程式需要您建立 Properties/launchSettings.json 檔案,而此檔案包括管理 URL 和管理連接埠。 如需詳細資訊,請參閱依連接埠篩選一節。

基本健康狀態探查

對於許多應用程式,報告應用程式是否可處理要求的基本健康狀態探查組態 (「活躍度」),便足以探索應用程式的狀態。

基本設定會登錄健康情況檢查服務,並呼叫健康情況檢查中介軟體以在具有健康情況回應的 URL 端點做出回應。 預設並未登錄特定健康狀態檢查來測試任何特定相依性或子系統。 如果應用程式可以在健康情況端點 URL 做出回應,則視為狀況良好。 預設回應寫入器會將狀態 (HealthStatus) 以純文字回應形式回寫至用戶端,指出 HealthStatus.HealthyHealthStatus.DegradedHealthStatus.Unhealthy 狀態。

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點。

在範例應用程式中,是在 /health (BasicStartup.cs) 建立健康情況檢查端點:

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

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

若要使用範例應用程式執行基本組態案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario basic

Docker 範例

Docker 提供內建 HEALTHCHECK 指示詞,可用來檢查使用基本健康狀態檢查組態的應用程式狀態:

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

建立健康狀態檢查

健康狀態檢查是藉由實作 IHealthCheck 介面來建立。 CheckHealthAsync 方法會傳回指出狀態為 HealthyDegradedUnhealthyHealthCheckResult。 結果會寫成具有可設定狀態碼的純文字回應 (健康狀態檢查選項一節中將說明如何進行組態)。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

下列 ExampleHealthCheck 類別示範健康情況檢查的配置。 健康情況檢查邏輯放在 CheckHealthAsync 方法中。 下列範例會將虛擬變數 healthCheckResultHealthy 設定為 true。 如果 healthCheckResultHealthy 的值設定為 false,則會傳回 HealthCheckResult.Unhealthy 狀態。

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("An unhealthy result."));
    }
}

登錄健康狀態檢查服務

Startup.ConfigureServices 中使用 AddCheck,以將 ExampleHealthCheck 類型新增至健康情況檢查服務:

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

下列範例中所顯示的 AddCheck 多載會設定在健康狀態檢查報告失敗時所要報告的失敗狀態 (HealthStatus)。 如果將失敗狀態設定為 null (預設),則會報告 HealthStatus.Unhealthy。 此多載對程式庫作者很有用。若健康狀態檢查實作採用此設定,則當健康狀態檢查失敗時,應用程式就會強制程式庫指出失敗狀態。

您可以使用「標籤」來篩選健康狀態檢查 (篩選健康狀態檢查一節中將進一步說明)。

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck 也可以執行匿名函式。 在下列範例中,健康狀態檢查名稱指定為 Example,且檢查一律會傳回狀況良好狀態:

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

呼叫 AddTypeActivatedCheck,以將引數傳遞至健康情況檢查實作。 在下列範例中,TestHealthCheckWithArgs 接受在呼叫 CheckHealthAsync 時使用整數和字串:

private class TestHealthCheckWithArgs : IHealthCheck
{
    public TestHealthCheckWithArgs(int i, string s)
    {
        I = i;
        S = s;
    }

    public int I { get; set; }

    public string S { get; set; }

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

使用傳遞至實作的整數和字串來呼叫 AddTypeActivatedCheck,以登錄 TestHealthCheckWithArgs

services.AddHealthChecks()
    .AddTypeActivatedCheck<TestHealthCheckWithArgs>(
        "test", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "example" }, 
        args: new object[] { 5, "string" });

使用健康情況檢查路由傳送

Startup.Configure 中,使用端點 URL 或相對路徑以在端點建立器上呼叫 MapHealthChecks

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

需要主機

呼叫 RequireHost,以將一或多個允許的主機指定給健康情況檢查端點。 主機應該是 Unicode,而不是 punycode,而且可能會包括連接埠。 如果未提供集合,則會接受任何主機。

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});

如需詳細資訊,請參閱依連接埠篩選一節。

需要授權

呼叫 RequireAuthorization,以在健康情況檢查要求端點上執行授權中介軟體。 RequireAuthorization 多載接受一或多個授權原則。 如果未提供原則,則會使用預設授權原則。

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireAuthorization();
});

啟用跨原始來源要求 (CORS)

雖然從瀏覽器手動執行健康情況檢查不是常見使用案例,但是您可以在健康情況檢查端點上呼叫 RequireCors,以啟用 CORS 中介軟體。 RequireCors 多載接受 CORS 原則建立器委派 (CorsPolicyBuilder) 或原則名稱。 如果未提供原則,則會使用預設 CORS 原則。 如需詳細資訊,請參閱在 ASP.NET Core 中啟用跨原始來源要求 (CORS)

健康狀態檢查選項

HealthCheckOptions 讓您有機會自訂健康狀態檢查行為:

篩選健康狀態檢查

根據預設,健康情況檢查中介軟體會執行所有已登錄的健康情況檢查。 若要執行健康狀態檢查子集,請對 Predicate 選項提供傳回布林值的函式。 在下列範例中,會依函式條件陳述式中的標籤 (bar_tag) 篩選出 Bar 健康狀態檢查。只有在健康狀態檢查的 Tags 屬性符合 foo_tagbaz_tag 時,才傳回 true

Startup.ConfigureServices 中:

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });

Startup.Configure 中,Predicate 會篩選出「橫條圖」健康情況檢查。 只有 Foo 和 Baz 才能執行:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
});

自訂 HTTP 狀態碼

您可以使用 ResultStatusCodes 來自訂健康狀態與 HTTP 狀態碼的對應。 下列 StatusCodes 指派是中介軟體所使用的預設值。 請變更狀態碼值以符合您的需求。

Startup.Configure 中:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        }
    });
});

隱藏快取標頭

AllowCachingResponses 會控制健康情況檢查中介軟體是否將 HTTP 標頭新增至探查回應,以防止回應快取。 如果值為 false (預設),則中介軟體會設定或覆寫 Cache-ControlExpiresPragma 標頭,以防止回應快取。 如果值為 true,則中介軟體不會修改回應的快取標頭。

Startup.Configure 中:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        AllowCachingResponses = true
    });
});

自訂輸出

Startup.Configure 中,將 HealthCheckOptions.ResponseWriter 選項設定為撰寫回應的委派:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
});

預設委派會使用字串值 HealthReport.Status 寫入基本純文字回應。 下列自訂委派會輸出自訂 JSON 回應。

範例應用程式中的第一個範例示範如何使用 System.Text.Json

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions
    {
        Indented = true
    };

    using (var stream = new MemoryStream())
    {
        using (var writer = new Utf8JsonWriter(stream, options))
        {
            writer.WriteStartObject();
            writer.WriteString("status", result.Status.ToString());
            writer.WriteStartObject("results");
            foreach (var entry in result.Entries)
            {
                writer.WriteStartObject(entry.Key);
                writer.WriteString("status", entry.Value.Status.ToString());
                writer.WriteString("description", entry.Value.Description);
                writer.WriteStartObject("data");
                foreach (var item in entry.Value.Data)
                {
                    writer.WritePropertyName(item.Key);
                    JsonSerializer.Serialize(
                        writer, item.Value, item.Value?.GetType() ??
                        typeof(object));
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }

        var json = Encoding.UTF8.GetString(stream.ToArray());

        return context.Response.WriteAsync(json);
    }
}

第二個範例示範如何使用 Newtonsoft.Json

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

在範例應用程式中,註解化 CustomWriterStartup.cs 中的 SYSTEM_TEXT_JSON前置處理器指示詞,以啟用 WriteResponseNewtonsoft.Json 版本。

健康情況檢查 API 未提供複雜 JSON 傳回格式的內建支援,因為此格式是您所選擇的監控系統所特有。 視需要,自訂上述範例中的回應。 如需使用 System.Text.Json 進行 JSON 序列化的詳細資訊,請參閱如何在 .NET 中序列化和還原序列化 JSON

資料庫探查

健康狀態檢查可指定資料庫查詢以布林測試方式來執行,藉此指出資料庫是否正常回應。

範例應用程式使用 AspNetCore.Diagnostics.HealthChecks (一種適用於 ASP.NET Core 應用程式的健康情況檢查程式庫),以在 SQL Server 資料庫上執行健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會對資料庫執行 SELECT 1 查詢,以確認資料庫連線狀況良好。

警告

使用查詢檢查資料庫連線時,請選擇快速傳回的查詢。 查詢方法具有多載資料庫而降低其效能的風險。 在大部分情況下,不需要執行測試查詢。 只要成功建立資料庫連線就已足夠。 如果您發現有必要執行查詢,請選擇簡單的 SELECT 查詢,例如 SELECT 1

包括 AspNetCore.HealthChecks.SqlServer 的套件參考。

在範例應用程式的 appsettings.json 檔案中,提供有效的資料庫連接字串。 應用程式使用名為 HealthCheckSample 的 SQL Server 資料庫:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  },
  "AllowedHosts": "*"
}

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 範例應用程式會使用資料庫連接字串 (DbHealthStartup.cs) 來呼叫 AddSqlServer 方法:

services.AddHealthChecks()
    .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks

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

若要使用範例應用程式執行資料庫探查案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario db

注意

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

Entity Framework Core DbContext 探查

DbContext 檢查會確認應用程式是否可以與針對 EF CoreDbContext 所設定的資料庫通訊。 應用程式支援 DbContext 檢查:

AddDbContextCheck<TContext> 會登錄 DbContext 的健康狀態檢查。 DbContext 會以 TContext 形式提供給方法。 多載可用來設定失敗狀態、標籤和自訂測試查詢。

預設情況:

  • DbContextHealthCheck 會呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態時所要執行的作業。
  • 健康狀態檢查的名稱是 TContext 類型的名稱。

在範例應用程式中,會將 AppDbContext 提供給 AddDbContextCheck,並在 Startup.ConfigureServices 中登錄為服務 (DbContextHealthStartup.cs):

services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(
        Configuration["ConnectionStrings:DefaultConnection"]);
});

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks

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

若要使用範例應用程式來執行 DbContext 探查案例,請確認 SQL Server 執行個體中沒有連接字串所指定的資料庫。 如果資料庫存在,請予以刪除。

在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario dbcontext

在應用程式執行之後,對瀏覽器中的 /health 端點提出要求來檢查健康狀態。 資料庫和 AppDbContext 不存在,因此應用程式會提供下列回應:

Unhealthy

觸發範例應用程式以建立資料庫。 對 /createdatabase 提出要求。 應用程式會回應:

Creating the database...
Done!
Navigate to /health to see the health status.

/health 端點提出要求。 資料庫和內容存在,因此應用程式會回應:

Healthy

觸發範例應用程式以刪除資料庫。 對 /deletedatabase 提出要求。 應用程式會回應:

Deleting the database...
Done!
Navigate to /health to see the health status.

/health 端點提出要求。 應用程式會提供狀況不良回應:

Unhealthy

個別的整備度與活躍度探查

在某些裝載案例中,會使用一組健康情況檢查來區分兩個應用程式狀態:

  • 「整備」指出應用程式是否正在正常執行,但尚未準備好接收要求。
  • 「活躍度」指出應用程式是否已當機,而且必須重新予以啟動。

請考慮下列範例:應用程式在準備好處理要求之前必須下載大型設定檔。 如果初始下載失敗,則我們不想要重新啟動應用程式,因為應用程式可以重試下載檔案數次。 我們使用「活躍度探查」來描述處理序的活躍度,而不會執行其他檢查。 我們也想要防止在設定檔下載成功之前將要求傳送至應用程式。 除非下載成功,而且應用程式準備好接收要求,否則我們會使用「整備度探查」來指出「尚未就緒」狀態。

範例應用程式包含健康狀態檢查,會在託管服務中長時間執行的啟動工作完成時回報。 StartupHostedServiceHealthCheck 會公開 StartupTaskCompleted 屬性,而裝載的服務可以在其長時間執行的工作完成時,將此屬性設定為 true (StartupHostedServiceHealthCheck.cs):

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

裝載的服務 (Services/StartupHostedService) 會啟動長時間執行的背景工作。 工作完成時,StartupHostedServiceHealthCheck.StartupTaskCompleted 會設定為 true

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger,
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

健康狀態檢查是 Startup.ConfigureServices 中使用 AddCheck 隨託管服務一起登錄。 因為所裝載服務必須在健康情況檢查上設定此屬性,所以也會在服務容器中登錄健康情況檢查 (LivenessProbeStartup.cs):

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 在範例應用程式中,是在下列位置建立健康情況檢查端點:

  • /health/ready 用於整備檢查。 整備度檢查使用 ready 標籤來篩選健康狀態檢查。
  • /health/live 用於活躍度檢查。 活躍度檢查是在 HealthCheckOptions.Predicate 中傳回 false 來篩選出 StartupHostedServiceHealthCheck (如需詳細資訊,請參閱篩選健康情況檢查)

在下列範例程式碼中:

  • 整備檢查會使用具有「就緒」標記的所有已登錄檢查。
  • Predicate 會排除所有檢查,並傳回 200-Ok。
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

若要使用範例應用程式執行整備度/活躍度組態案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario liveness

在瀏覽器中,瀏覽 /health/ready 數次,直到經過 15 秒。 健康狀態檢查報告前 15 秒為 Unhealthy。 15 秒之後,端點會報告 Healthy,以反映託管服務長時間執行的工作已完成。

此範例也會建立一個以兩秒延遲執行第一次整備檢查的「健康情況檢查發行者」(IHealthCheckPublisher 實作)。 如需詳細資訊,請參閱健康狀態檢查發行者一節。

Kubernetes 範例

使用個別的整備度與活躍度檢查在 Kubernetes 之類的環境中很有用。 在 Kubernetes 中,應用程式可能需要先執行耗時的啟動工作,才能接受要求 (例如基礎資料庫可用性測試)。 使用個別的檢查可讓協調器區分應用程式是否為正常運作但尚未準備好,或應用程式是否無法啟動。 如需 Kubernetes 中整備度與活躍度探查的詳細資訊,請參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設定活躍度與整備度探查)。

下列範例示範 Kubernetes 整備度探查組態:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

透過自訂回應寫入器的計量型探查

範例應用程式示範透過自訂回應寫入器的記憶體健康狀態檢查。

如果應用程式使用超過指定的記憶體閾值 (在範例應用程式中為 1 GB),MemoryHealthCheck 會報告降級的狀態。 HealthCheckResult 包括應用程式的記憶體回收行程 (GC) 資訊 (MemoryHealthCheck.cs):

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
        var status = (allocated < options.Threshold) ?
            HealthStatus.Healthy : context.Registration.FailureStatus;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 MemoryHealthCheck 會登錄為服務,而不是將健康狀態檢查傳遞至 AddCheck 以啟用檢查。 所有 IHealthCheck 登錄的服務都可供健康狀態檢查服務和中介軟體使用。 建議將健康狀態檢查服務登錄為單一服務。

在範例應用程式的 CustomWriterStartup.cs 中:

services.AddHealthChecks()
    .AddMemoryHealthCheck("memory");

健康情況檢查端點的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 健康情況檢查執行時,會將 WriteResponse 委派提供給 ResponseWriter 屬性以輸出自訂 JSON 回應:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
}

WriteResponse 委派會將 CompositeHealthCheckResult 格式化為 JSON 物件,並產生健康情況檢查回應的 JSON 輸出。 如需詳細資訊,請參閱自訂輸出小節。

若要使用範例應用程式透過自訂回應寫入器輸出執行計量型探查,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario writer

注意

AspNetCore.Diagnostics.HealthChecks 包括計量型健康情況檢查案例,包括磁碟儲存體和最大值活躍度檢查。

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

依連接埠篩選

使用 URL 模式以在 MapHealthChecks 上呼叫 RequireHost,而此模式指定連接埠來限制針對所指定連接埠的健康情況檢查要求。 此方式通常用於容器環境,以公開監控服務的連接埠。

範例應用程式使用環境變數組態提供者來設定連接埠。 連接埠是在 launchSettings.json 檔案中設定,並透過環境變數傳遞至設定提供者。 您也必須將伺服器設定為在管理連接埠上接聽要求。

若要使用範例應用程式來示範管理連接埠設定,請在 Properties 資料夾中建立 launchSettings.json 檔案。

範例應用程式中的下列 Properties/launchSettings.json 檔案未包括在範例應用程式的專案檔中,而且必須手動予以建立:

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點。

在範例應用程式中,對 Startup.Configure 中端點的 RequireHost 呼叫指定設定管理連接埠:

endpoints.MapHealthChecks("/health")
    .RequireHost($"*:{Configuration["ManagementPort"]}");

在範例應用程式的 Startup.Configure 中,建立端點。 在下列範例程式碼中:

  • 整備檢查會使用具有「就緒」標記的所有已登錄檢查。
  • Predicate 會排除所有檢查,並傳回 200-Ok。
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

注意

您可以在程式碼中明確設定管理連接埠,以避免在範例應用程式中建立 launchSettings.json 檔案。 在 HostBuilder 建立所在的 Program.cs 中,新增 ListenAnyIP 呼叫,並提供應用程式的管理連接埠端點。 在 ManagementPortStartup.csConfigure 中,使用 RequireHost 來指定管理連接埠:

Program.cs

return new HostBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel()
            .ConfigureKestrel(serverOptions =>
            {
                serverOptions.ListenAnyIP(5001);
            })
            .UseStartup(startupType);
    })
    .Build();

ManagementPortStartup.cs

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});

若要使用範例應用程式執行管理連接埠組態案例,請在命令殼層中執行來自專案資料夾的下列命令:

dotnet run --scenario port

發佈健康狀態檢查程式庫

若要發佈健康狀態檢查作為程式庫:

  1. 寫入健康狀態檢查,將 IHealthCheck 介面當做獨立類別來實作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項來存取組態資料。

    CheckHealthAsync 的健全狀況檢查邏輯中:

    • data1data2 用於此方法,以執行探查的健康情況檢查邏輯。
    • 已處理 AccessViolationException

    發生 AccessViolationException 時,會使用 HealthCheckResult 來傳回 FailureStatus,以允許使用者設定健康情況檢查失敗狀態。

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    namespace SampleApp
    {
        public class ExampleHealthCheck : IHealthCheck
        {
            private readonly string _data1;
            private readonly int? _data2;
    
            public ExampleHealthCheck(string data1, int? data2)
            {
                _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
                _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
            }
    
            public async Task<HealthCheckResult> CheckHealthAsync(
                HealthCheckContext context, CancellationToken cancellationToken)
            {
                try
                {
                    return HealthCheckResult.Healthy();
                }
                catch (AccessViolationException ex)
                {
                    return new HealthCheckResult(
                        context.Registration.FailureStatus,
                        description: "An access violation occurred during the check.",
                        exception: ex,
                        data: null);
                }
            }
        }
    }
    
  2. 使用取用應用程式在其 Startup.Configure 方法中呼叫的參數,來寫入延伸模組。 在下列範例中,假設健康狀態檢查方法簽章如下:

    ExampleHealthCheck(string, string, int )
    

    上述簽章指出 ExampleHealthCheck 需要額外的資料,才能處理健康狀態檢查探查邏輯。 此資料會提供給委派,以在使用延伸模組登錄健康狀態檢查時,用來建立健康狀態檢查執行個體。 在下列範例中,呼叫者會選擇性地指定:

    • 健康狀態檢查名稱 (name)。 如果為 null,則會使用 example_health_check
    • 健康狀態檢查的字串資料點 (data1)。
    • 健康狀態檢查的整數資料點 (data2)。 如果為 null,則會使用 1
    • 失敗狀態 (HealthStatus)。 預設值為 null。 如果為 null,則會報告失敗狀態為 HealthStatus.Unhealthy
    • 標籤 (IEnumerable<string>)。
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

健康狀態檢查發行者

IHealthCheckPublisher 新增至服務容器時,健康狀態檢查系統會定期執行健康狀態檢查,並呼叫 PublishAsync 傳回結果。 這對推送型健康狀態監控系統案例很有用,其預期每個處理序會定期呼叫監控系統來判斷健康狀態。

IHealthCheckPublisher 介面有單一方法:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions 可讓您設定:

  • Delay:初始延遲會在應用程式啟動之後且執行 IHealthCheckPublisher 執行個體之前套用。 在啟動後就會套用延遲,但不會套用至後續的反覆項目。 預設值是五秒鐘。
  • PeriodIHealthCheckPublisher 執行的期間。 預設值為 30 秒。
  • Predicate:如果 Predicatenull (預設),則健康情況檢查發行者服務會執行所有已登錄的健康情況檢查。 若要執行一部分的健康狀態檢查,請提供可篩選該組檢查的函式。 每個期間都會評估該述詞。
  • Timeout:執行所有 IHealthCheckPublisher 執行個體之健康情況檢查的逾時。 若要在沒有逾時的情況下執行,請使用 InfiniteTimeSpan。 預設值為 30 秒。

在範例應用程式中,ReadinessPublisher 是一個 IHealthCheckPublisher 實作。 在下列記錄層級,會記錄每個檢查的健康情況檢查狀態:

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks
    // Middleware already logs health checks results. A real-world readiness
    // check in a production app might perform a set of more expensive or
    // time-consuming checks to determine if other resources are responding
    // properly.
    public Task PublishAsync(HealthReport report,
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

在範例應用程式的 LivenessProbeStartup 範例中,StartupHostedService 整備檢查具有 2 秒的啟動延遲,且每 30 秒會執行一次檢查。 為了啟用 IHealthCheckPublisher 實作,此範例會在相依性插入 (DI) 容器中將 ReadinessPublisher 註冊為單一服務:

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

注意

AspNetCore.Diagnostics.HealthChecks 包括數個系統的發行者,包括 Application Insights

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

利用 MapWhen 限制健康情況檢查

使用 MapWhen 來有條件地將健康情況檢查端點的要求管線分支。

在下列範例中,如果接收到 api/HealthCheck 端點的 GET 要求,則 MapWhen 會對要求管線進行分支處理,以啟用健康情況檢查中介軟體:

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});

如需詳細資訊,請參閱 ASP.NET Core 中介軟體

ASP.NET Core 提供健康情況檢查中介軟體和程式庫,用來報告應用程式基礎結構元件的健康情況。

應用程式會將健康狀態檢查公開為 HTTP 端點。 您可以針對各種即時監控案例來設定健康情況檢查端點:

  • 容器協調器和負載平衡器可以使用健康狀態探查,來檢查應用程式的狀態。 例如,容器協調器可能會暫停輪流部署或重新啟動容器,來回應失敗的健康狀態檢查。 負載平衡器可能會將流量從失敗的執行個體路由傳送至狀況良好的執行個體,來回應狀況不良的應用程式。
  • 您可以監控所使用記憶體、磁碟及其他實體伺服器資源的健康狀態。
  • 健康狀態檢查可以測試應用程式的相依性 (例如資料庫和外部服務端點),確認其是否可用且正常運作。

健康情況檢查通常會與外部監控服務或容器協調器搭配使用,來檢查應用程式的狀態。 將健康狀態檢查新增至應用程式之前,請決定要使用的監控系統。 監控系統會指定要建立哪些健康狀態檢查類型,以及如何設定其端點。

基本健康狀態探查

對於許多應用程式,報告應用程式是否可處理要求的基本健康狀態探查組態 (「活躍度」),便足以探索應用程式的狀態。

基本設定會登錄健康情況檢查服務,並呼叫健康情況檢查中介軟體以在具有健康情況回應的 URL 端點做出回應。 預設並未登錄特定健康狀態檢查來測試任何特定相依性或子系統。 如果應用程式可以在健康情況端點 URL 做出回應,則視為狀況良好。 預設回應寫入器會將 HealthStatus 以純文字回應形式寫入至用戶端。 HealthStatusHealthStatus.HealthyHealthStatus.DegradedHealthStatus.Unhealthy

Program.cs 中,使用 AddHealthChecks 登錄健康狀態檢查服務。 呼叫 MapHealthChecks 來建立健康情況檢查端點。

下列範例會在 /healthz 建立健康情況檢查端點:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

Docker HEALTHCHECK

Docker 提供內建 HEALTHCHECK 指示詞,可用來檢查使用基本健康狀態檢查組態的應用程式狀態:

HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit

上述範例會使用 curl,以在 /healthz 針對健康情況檢查端點提出 HTTP 要求。 curl 未包括在 .NET Linux 容器映像中,但可以在 Dockerfile 中安裝必要套件來進行新增。 根據 Alpine Linux 來使用映像的容器可以使用所包括的 wget 來取代 curl

建立健康狀態檢查

健康狀態檢查是藉由實作 IHealthCheck 介面來建立。 CheckHealthAsync 方法會傳回指出狀態為 HealthyDegradedUnhealthyHealthCheckResult。 結果會寫成具有可設定狀態碼的純文字回應。 健康情況檢查選項小節中會描述設定。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

下列範例示範健康情況檢查的配置:

public class SampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

健康情況檢查的邏輯放在 CheckHealthAsync 方法中。 上述範例會將虛擬變數 isHealthy 設定為 true。 如果 isHealthy 的值設定為 false,則會傳回 HealthCheckRegistration.FailureStatus 狀態。

如果 CheckHealthAsync 在檢查期間擲回例外狀況,則會傳回其 HealthReportEntry.Status 設定為 FailureStatus 的新 HealthReportEntry。 此狀態是由 AddCheck 所定義 (請參閱登錄健康情況檢查服務一節),並包括造成檢查失敗的內部例外狀況Description 會設定為例外狀況的訊息。

登錄健康狀態檢查服務

若要登錄健康情況檢查服務,請在 Program.cs 中呼叫 AddCheck

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>("Sample");

下列範例中所顯示的 AddCheck 多載會設定在健康狀態檢查報告失敗時所要報告的失敗狀態 (HealthStatus)。 如果將失敗狀態設定為 null (預設),則會報告 HealthStatus.Unhealthy。 此多載對程式庫作者很有用。若健康狀態檢查實作採用此設定,則當健康狀態檢查失敗時,應用程式就會強制程式庫指出失敗狀態。

「標記」可以用來篩選健康情況檢查。 標記會在篩選健康情況檢查小節中予以描述。

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" });

AddCheck 也可以執行匿名函式。 在下列範例中,健康情況檢查一律會傳回狀況良好結果:

builder.Services.AddHealthChecks()
    .AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));

呼叫 AddTypeActivatedCheck,以將引數傳遞至健康情況檢查實作。 在下列範例中,啟用類型的健康情況檢查會在其建構函式中接受整數和字串:

public class SampleHealthCheckWithArgs : IHealthCheck
{
    private readonly int _arg1;
    private readonly string _arg2;

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // ...

        return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
    }
}

若要登錄上述健康情況檢查,請使用傳遞為引數的整數和字串來呼叫 AddTypeActivatedCheck

builder.Services.AddHealthChecks()
    .AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" },
        args: new object[] { 1, "Arg" });

使用健康情況檢查路由傳送

Program.cs 中,使用端點 URL 或相對路徑以在端點建立器上呼叫 MapHealthChecks

app.MapHealthChecks("/healthz");

需要主機

呼叫 RequireHost,以將一或多個允許的主機指定給健康情況檢查端點。 主機應該是 Unicode,而不是 punycode,而且可能會包括連接埠。 如果未提供集合,則會接受任何主機:

app.MapHealthChecks("/healthz")
    .RequireHost("www.contoso.com:5001");

若要限制健康情況檢查端點只在特定連接埠上回應,請在 RequireHost 呼叫中指定連接埠。 此方式通常用於容器環境,以公開監控服務的連接埠:

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001");

警告

依賴於主機標頭的 API (例如 HttpRequest.HostRequireHost) 可能會受到用戶端的詐騙。

若要防止主機和連接埠詐騙,請使用下列其中一種方式:

若要防止未經授權的用戶端詐騙連接埠,請呼叫 RequireAuthorization

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001")
    .RequireAuthorization();

如需詳細資訊,請參閱具有 RequireHost 之路由中的主機比對

需要授權

呼叫 RequireAuthorization,以在健康情況檢查要求端點上執行授權中介軟體。 RequireAuthorization 多載接受一或多個授權原則。 如果未提供原則,則會使用預設授權原則:

app.MapHealthChecks("/healthz")
    .RequireAuthorization();

啟用跨原始來源要求 (CORS)

雖然從瀏覽器手動執行健康情況檢查不是常見案例,但是您可以在健康情況檢查端點上呼叫 RequireCors,以啟用 CORS 中介軟體。 RequireCors 多載接受 CORS 原則建立器委派 (CorsPolicyBuilder) 或原則名稱。 如需詳細資訊,請參閱在 ASP.NET Core 中啟用跨原始來源要求 (CORS)

健康狀態檢查選項

HealthCheckOptions 讓您有機會自訂健康狀態檢查行為:

篩選健康狀態檢查

根據預設,健康情況檢查中介軟體會執行所有已登錄的健康情況檢查。 若要執行健康狀態檢查子集,請對 Predicate 選項提供傳回布林值的函式。

下列範例會篩選健康情況檢查,以只執行已標記 sample 的檢查:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});

自訂 HTTP 狀態碼

您可以使用 ResultStatusCodes 來自訂健康狀態與 HTTP 狀態碼的對應。 下列 StatusCodes 指派是中介軟體所使用的預設值。 變更狀態碼值,以符合您的需求:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResultStatusCodes =
    {
        [HealthStatus.Healthy] = StatusCodes.Status200OK,
        [HealthStatus.Degraded] = StatusCodes.Status200OK,
        [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
    }
});

隱藏快取標頭

AllowCachingResponses 會控制健康情況檢查中介軟體是否將 HTTP 標頭新增至探查回應,以防止回應快取。 如果值為 false (預設),則中介軟體會設定或覆寫 Cache-ControlExpiresPragma 標頭,以防止回應快取。 如果值為 true,則中介軟體不會修改回應的快取標頭:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    AllowCachingResponses = true
});

自訂輸出

若要自訂健康情況檢查報告的輸出,請將 HealthCheckOptions.ResponseWriter 屬性設定為可寫入回應的委派:

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResponseWriter = WriteResponse
});

預設委派會使用字串值 HealthReport.Status 寫入基本純文字回應。 下列自訂委派會使用 System.Text.Json 來輸出自訂 JSON 回應:

private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions { Indented = true };

    using var memoryStream = new MemoryStream();
    using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
    {
        jsonWriter.WriteStartObject();
        jsonWriter.WriteString("status", healthReport.Status.ToString());
        jsonWriter.WriteStartObject("results");

        foreach (var healthReportEntry in healthReport.Entries)
        {
            jsonWriter.WriteStartObject(healthReportEntry.Key);
            jsonWriter.WriteString("status",
                healthReportEntry.Value.Status.ToString());
            jsonWriter.WriteString("description",
                healthReportEntry.Value.Description);
            jsonWriter.WriteStartObject("data");

            foreach (var item in healthReportEntry.Value.Data)
            {
                jsonWriter.WritePropertyName(item.Key);

                JsonSerializer.Serialize(jsonWriter, item.Value,
                    item.Value?.GetType() ?? typeof(object));
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WriteEndObject();
        }

        jsonWriter.WriteEndObject();
        jsonWriter.WriteEndObject();
    }

    return context.Response.WriteAsync(
        Encoding.UTF8.GetString(memoryStream.ToArray()));
}

健康情況檢查 API 未提供複雜 JSON 傳回格式的內建支援,因為此格式是您所選擇的監控系統所特有。 視需要,自訂上述範例中的回應。 如需使用 System.Text.Json 進行 JSON 序列化的詳細資訊,請參閱如何在 .NET 中序列化和還原序列化 JSON

資料庫探查

健康狀態檢查可指定資料庫查詢以布林測試方式來執行,藉此指出資料庫是否正常回應。

AspNetCore.Diagnostics.HealthChecks,一種適用於 ASP.NET Core 應用程式的健康情況檢查程式庫,包括針對 SQL Server 資料庫所執行的健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會對資料庫執行 SELECT 1 查詢,以確認資料庫連線狀況良好。

警告

使用查詢檢查資料庫連線時,請選擇快速傳回的查詢。 查詢方法具有多載資料庫而降低其效能的風險。 在大部分情況下,不需要執行測試查詢。 只要成功建立資料庫連線就已足夠。 如果您發現有必要執行查詢,請選擇簡單的 SELECT 查詢,例如 SELECT 1

若要使用此 SQL Server 健康情況檢查,請包括 AspNetCore.HealthChecks.SqlServer NuGet 套件的套件參考。 下列範例會登錄 SQL Server 健康情況檢查:

builder.Services.AddHealthChecks()
    .AddSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection"));

注意

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

Entity Framework Core DbContext 探查

DbContext 檢查會確認應用程式是否可以與針對 EF CoreDbContext 所設定的資料庫通訊。 應用程式支援 DbContext 檢查:

AddDbContextCheck 會登錄 DbContext 的健康狀態檢查。 DbContext 會以 TContext 形式提供給方法。 多載可用來設定失敗狀態、標籤和自訂測試查詢。

預設情況:

  • DbContextHealthCheck 會呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態時所要執行的作業。
  • 健康狀態檢查的名稱是 TContext 類型的名稱。

下列範例會登錄 DbContext 和相關聯的 DbContextHealthCheck

builder.Services.AddDbContext<SampleDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddHealthChecks()
    .AddDbContextCheck<SampleDbContext>();

個別的整備度與活躍度探查

在某些裝載案例中,會使用一組健康情況檢查來區分兩個應用程式狀態:

  • 「整備」指出應用程式是否正在正常執行,但尚未準備好接收要求。
  • 「活躍度」指出應用程式是否已當機,而且必須重新予以啟動。

請考慮下列範例:應用程式在準備好處理要求之前必須下載大型設定檔。 如果初始下載失敗,則我們不想要重新啟動應用程式,因為應用程式可以重試下載檔案數次。 我們使用「活躍度探查」來描述處理序的活躍度,而不會執行其他檢查。 我們也想要防止在設定檔下載成功之前將要求傳送至應用程式。 除非下載成功,而且應用程式準備好接收要求,否則我們會使用「整備度探查」來指出「尚未就緒」狀態。

下列背景工作會模擬大約需要 15 秒的啟動處理序。 完成後,工作會將 StartupHealthCheck.StartupCompleted 屬性設定為 True:

public class StartupBackgroundService : BackgroundService
{
    private readonly StartupHealthCheck _healthCheck;

    public StartupBackgroundService(StartupHealthCheck healthCheck)
        => _healthCheck = healthCheck;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Simulate the effect of a long-running task.
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _healthCheck.StartupCompleted = true;
    }
}

StartupHealthCheck 會報告長時間執行的啟動工作完成,並公開背景服務所設定的 StartupCompleted 屬性:

public class StartupHealthCheck : IHealthCheck
{
    private volatile bool _isReady;

    public bool StartupCompleted
    {
        get => _isReady;
        set => _isReady = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        if (StartupCompleted)
        {
            return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
        }

        return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
    }
}

健康狀態檢查是 Program.cs 中使用 AddCheck 隨託管服務一起登錄。 因為所裝載服務必須在健康情況檢查上設定此屬性,所以也會在服務容器中將健康情況檢查登錄為單一資料庫:

builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();

builder.Services.AddHealthChecks()
    .AddCheck<StartupHealthCheck>(
        "Startup",
        tags: new[] { "ready" });

若要建立兩個不同的健康情況檢查端點,請呼叫 MapHealthChecks 兩次:

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});

app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
    Predicate = _ => false
});

上述範例會建立下列健康情況檢查端點:

  • /healthz/ready 用於整備檢查。 整備檢查會將健康情況檢查篩選為已標記 ready 的檢查。
  • /healthz/live 用於活躍度檢查。 活躍度檢查會在 HealthCheckOptions.Predicate 委派中傳回 false,以篩選出所有健康情況檢查。 如需篩選健康情況檢查的詳細資訊,請參閱本文中的篩選健康情況檢查

啟動工作完成之前,/healthz/ready 端點會回報 Unhealthy 狀態。 啟動工作完成之後,此端點會回報 Healthy 狀態。 /healthz/live 端點會排除所有檢查,並將所有呼叫的狀態都回報為 Healthy

Kubernetes 範例

使用個別的整備度與活躍度檢查在 Kubernetes 之類的環境中很有用。 在 Kubernetes 中,應用程式可能需要先執行耗時的啟動工作,才能接受要求 (例如基礎資料庫可用性測試)。 使用個別的檢查可讓協調器區分應用程式是否為正常運作但尚未準備好,或應用程式是否無法啟動。 如需 Kubernetes 中整備度與活躍度探查的詳細資訊,請參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設定活躍度與整備度探查)。

下列範例示範 Kubernetes 整備度探查組態:

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /healthz/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

發佈健康狀態檢查程式庫

若要發佈健康狀態檢查作為程式庫:

  1. 寫入健康狀態檢查,將 IHealthCheck 介面當做獨立類別來實作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項來存取組態資料。

  2. 使用取用應用程式在其 Program.cs 方法中呼叫的參數,來寫入延伸模組。 請考慮下列範例健康情況檢查,而此檢查接受 arg1arg2 作為建構函式參數:

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);
    

    上述簽章指出健康情況檢查需要自訂資料,才能處理健康情況檢查探查邏輯。 此資料會提供給委派,以在使用延伸模組登錄健康狀態檢查時,用來建立健康狀態檢查執行個體。 在下列範例中,呼叫端會指定:

    • arg1:健康情況檢查的整數資料點。
    • arg2:健康情況檢查的字串引數。
    • name:選用的健康情況檢查名稱。 如果 null,則會使用預設值。
    • failureStatus:選用的 HealthStatus,其回報失敗狀態。 如果為 null,則會使用 HealthStatus.Unhealthy
    • tags:標記的選用 IEnumerable<string> 集合。
    public static class SampleHealthCheckBuilderExtensions
    {
        private const string DefaultName = "Sample";
    
        public static IHealthChecksBuilder AddSampleHealthCheck(
            this IHealthChecksBuilder healthChecksBuilder,
            int arg1,
            string arg2,
            string? name = null,
            HealthStatus? failureStatus = null,
            IEnumerable<string>? tags = default)
        {
            return healthChecksBuilder.Add(
                new HealthCheckRegistration(
                    name ?? DefaultName,
                    _ => new SampleHealthCheckWithArgs(arg1, arg2),
                    failureStatus,
                    tags));
        }
    }
    

健康狀態檢查發行者

IHealthCheckPublisher 新增至服務容器時,健康狀態檢查系統會定期執行健康狀態檢查,並呼叫 PublishAsync 傳回結果。 此處理序適用於推送型健康情況監控系統案例,而此案例預期每個處理序都會定期呼叫監控系統來判斷健康情況。

HealthCheckPublisherOptions 可讓您設定:

  • Delay:初始延遲會在應用程式啟動之後且執行 IHealthCheckPublisher 執行個體之前套用。 啟動後就會套用延遲,但不會套用至後面的反覆項目。 預設值是五秒鐘。
  • PeriodIHealthCheckPublisher 執行的期間。 預設值為 30 秒。
  • Predicate:如果 Predicatenull (預設),則健康情況檢查發行者服務會執行所有已登錄的健康情況檢查。 若要執行一部分的健康狀態檢查,請提供可篩選該組檢查的函式。 每個期間都會評估該述詞。
  • Timeout:執行所有 IHealthCheckPublisher 執行個體之健康情況檢查的逾時。 若要在沒有逾時的情況下執行,請使用 InfiniteTimeSpan。 預設值為 30 秒。

下列範例示範健康情況發行者的配置:

public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            // ...
        }
        else
        {
            // ...
        }

        return Task.CompletedTask;
    }
}

HealthCheckPublisherOptions 類別提供屬性來設定健康情況檢查發行者的行為。

下列範例會將健康情況檢查發行者登錄為單一資料庫,並設定 HealthCheckPublisherOptions

builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});

builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();

注意

AspNetCore.Diagnostics.HealthChecks 包括數個系統的發行者,包括 Application Insights

Microsoft 不會維護或支援 AspNetCore.Diagnostics.HealthChecks

相依性插入和健康情況檢查

您可以使用相依性插入來取用健康情況檢查類別內特定 Type 的執行個體。 相依性插入適用於將選項或全域設定插入至健康情況檢查。 使用相依性插入「不」是設定健康情況檢查的常見案例。 通常,每個健康情況檢查都是專屬於實際測試,並且使用 IHealthChecksBuilder 擴充方法進行設定。

下列範例顯示可透過相依性插入來擷取設定物件的範例健康情況檢查:

public class SampleHealthCheckWithDI : IHealthCheck
{
    private readonly SampleHealthCheckWithDiConfig _config;

    public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
        => _config = config;

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // use _config ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

SampleHealthCheckWithDiConfig 和健康情況檢查需要新增至服務容器:

builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
    BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheckWithDI>(
        "With Dependency Injection",
        tags: new[] { "inject" });

UseHealthChecks 與MapHealthChecks

有兩種方式可讓呼叫端存取健康情況檢查:

  • UseHealthChecks 會登錄中介軟體來處理中介軟體管線中的健康情況檢查要求。
  • MapHealthChecks 會登錄健康情況檢查端點。 端點會與應用程式中的其他端點進行比對和執行。

使用 MapHealthChecks 優於 UseHealthChecks 的優點是能夠使用端點感知中介軟體 (例如授權),並更精細地控制比對原則。 使用 UseHealthChecks 優於 MapHealthChecks 的主要優點是確切控制中介軟體管線中執行健康情況檢查的位置。

UseHealthChecks

  • 在要求符合健康情況檢查端點時終止管線。 最短線路可避免不必要的工作,因此經常使用 (例如記錄和其他中介軟體)。
  • 主要用於在管線中設定健康情況檢查中介軟體。
  • 可以比對連接埠上的任何路徑與 null 或空白 PathString。 允許在針對所指定連接埠所提出的任何要求上執行健康情況檢查。
  • 原始程式碼

MapHealthChecks 允許:

  • 對應特定路由或端點以進行健康情況檢查。
  • 自訂可存取健康情況檢查端點的 URL 或路徑。
  • 使用不同的路由或設定來對應多個健康情況檢查端點。 多個端點支援:
    • 針對不同類型的健康情況檢查或元件啟用不同的端點。
    • 用來區分應用程式健康情況的不同層面,或將特定設定套用至健康情況檢查的子集。
  • 原始程式碼

其他資源

注意

本文部分是透過人工智慧協助建立的。 發佈之前,請視需要進行作者檢閱並修訂內容。 請參閱 Microsoft Learn 中我們對 AI 產生的內容之使用原則