首頁(yè) 資訊 ASP.NET Core 中的健康狀態(tài)檢查

ASP.NET Core 中的健康狀態(tài)檢查

來(lái)源:泰然健康網(wǎng) 時(shí)間:2024年12月13日 15:59
跳到主要內(nèi)容

已不再支援此瀏覽器。

請(qǐng)升級(jí)至 Microsoft Edge,以利用最新功能、安全性更新和技術(shù)支援。

ASP.NET Core 中的健康狀態(tài)檢查

發(fā)行項(xiàng)2024/11/06

本文內(nèi)容

基本健康狀態(tài)探查建立健康狀態(tài)檢查登錄健康狀態(tài)檢查服務(wù)使用健康情況檢查路由傳送健康狀態(tài)檢查選項(xiàng)資料庫(kù)探查Entity Framework Core DbContext 探查個(gè)別的整備度與活躍度探查發(fā)佈健康狀態(tài)檢查程式庫(kù)健康狀態(tài)檢查發(fā)行者相依性插入和健康情況檢查UseHealthChecks 與MapHealthChecks其他資源

作者:Glenn Condron 和 Juergen Gutsch

注意

這不是這篇文章的最新版本。 如需目前的版本,請(qǐng)參閱 本文的 .NET 9 版本。

重要

這些發(fā)行前產(chǎn)品的相關(guān)資訊在產(chǎn)品正式發(fā)行前可能會(huì)有大幅修改。 Microsoft 對(duì)此處提供的資訊,不做任何明確或隱含的瑕疵擔(dān)保。

如需目前的版本,請(qǐng)參閱 本文的 .NET 9 版本。

ASP.NET Core 提供健康情況檢查中介軟體和程式庫(kù),用來(lái)報(bào)告應(yīng)用程式基礎(chǔ)結(jié)構(gòu)元件的健康情況。

應(yīng)用程式會(huì)將健康狀態(tài)檢查公開(kāi)為 HTTP 端點(diǎn)。 您可以針對(duì)各種即時(shí)監(jiān)控案例來(lái)設(shè)定健康情況檢查端點(diǎn):

容器協(xié)調(diào)器和負(fù)載平衡器可以使用健康狀態(tài)探查,來(lái)檢查應(yīng)用程式的狀態(tài)。 例如,容器協(xié)調(diào)器可能會(huì)暫停輪流部署或重新啟動(dòng)容器,來(lái)回應(yīng)失敗的健康狀態(tài)檢查。 負(fù)載平衡器可能會(huì)將流量從失敗的執(zhí)行個(gè)體路由傳送至狀況良好的執(zhí)行個(gè)體,來(lái)回應(yīng)狀況不良的應(yīng)用程式。 您可以監(jiān)控所使用記憶體、磁碟及其他實(shí)體伺服器資源的健康狀態(tài)。 健康狀態(tài)檢查可以測(cè)試應(yīng)用程式的相依性 (例如資料庫(kù)和外部服務(wù)端點(diǎn)),確認(rèn)其是否可用且正常運(yùn)作。

健康情況檢查通常會(huì)與外部監(jiān)控服務(wù)或容器協(xié)調(diào)器搭配使用,來(lái)檢查應(yīng)用程式的狀態(tài)。 將健康狀態(tài)檢查新增至應(yīng)用程式之前,請(qǐng)決定要使用的監(jiān)控系統(tǒng)。 監(jiān)控系統(tǒng)會(huì)指定要建立哪些健康狀態(tài)檢查類型,以及如何設(shè)定其端點(diǎn)。

基本健康狀態(tài)探查

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

基本設(shè)定會(huì)登錄健康情況檢查服務(wù),並呼叫健康情況檢查中介軟體以在具有健康情況回應(yīng)的 URL 端點(diǎn)做出回應(yīng)。 預(yù)設(shè)並未登錄特定健康狀態(tài)檢查來(lái)測(cè)試任何特定相依性或子系統(tǒng)。 如果應(yīng)用程式可以在健康情況端點(diǎn) URL 做出回應(yīng),則視為狀況良好。 預(yù)設(shè)回應(yīng)寫(xiě)入器會(huì)將 HealthStatus 以純文字回應(yīng)形式寫(xiě)入至用戶端。 HealthStatus 是 HealthStatus.Healthy、HealthStatus.Degraded 或 HealthStatus.Unhealthy。

在 Program.cs 中,使用 AddHealthChecks 登錄健康狀態(tài)檢查服務(wù)。 呼叫 MapHealthChecks 來(lái)建立健康情況檢查端點(diǎn)。

下列範(fàn)例會(huì)在 /healthz 建立健康情況檢查端點(diǎn):

var builder = WebApplication.CreateBuilder(args); builder.Services.AddHealthChecks(); var app = builder.Build(); app.MapHealthChecks("/healthz"); app.Run();

Docker HEALTHCHECK

Docker 提供內(nèi)建 HEALTHCHECK 指示詞,可用來(lái)檢查使用基本健康狀態(tài)檢查組態(tài)的應(yīng)用程式狀態(tài):

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

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

建立健康狀態(tài)檢查

健康狀態(tài)檢查是藉由實(shí)作 IHealthCheck 介面來(lái)建立。 CheckHealthAsync 方法會(huì)傳回指出狀態(tài)為 Healthy、Degraded 或 Unhealthy 的 HealthCheckResult。 結(jié)果會(huì)寫(xiě)成具有可設(shè)定狀態(tài)碼的純文字回應(yīng)。 健康情況檢查選項(xiàng)小節(jié)中會(huì)描述設(shè)定。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

下列範(fàn)例示範(fàn)健康情況檢查的配置:

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 方法中。 上述範(fàn)例會(huì)將虛擬變數(shù) isHealthy 設(shè)定為 true。 如果 isHealthy 的值設(shè)定為 false,則會(huì)傳回 HealthCheckRegistration.FailureStatus 狀態(tài)。

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

登錄健康狀態(tài)檢查服務(wù)

若要登錄健康情況檢查服務(wù),請(qǐng)?jiān)?Program.cs 中呼叫 AddCheck:

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

下列範(fàn)例中所顯示的 AddCheck 多載會(huì)設(shè)定在健康狀態(tài)檢查報(bào)告失敗時(shí)所要報(bào)告的失敗狀態(tài) (HealthStatus)。 如果將失敗狀態(tài)設(shè)定為 null (預(yù)設(shè)),則會(huì)報(bào)告 HealthStatus.Unhealthy。 此多載對(duì)程式庫(kù)作者很有用。若健康狀態(tài)檢查實(shí)作採(cǎi)用此設(shè)定,則當(dāng)健康狀態(tài)檢查失敗時(shí),應(yīng)用程式就會(huì)強(qiáng)制程式庫(kù)指出失敗狀態(tài)。

「標(biāo)記」可以用來(lái)篩選健康情況檢查。 標(biāo)記會(huì)在篩選健康情況檢查小節(jié)中予以描述。

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

AddCheck 也可以執(zhí)行匿名函式。 在下列範(fàn)例中,健康情況檢查一律會(huì)傳回狀況良好結(jié)果:

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

呼叫 AddTypeActivatedCheck,以將引數(shù)傳遞至健康情況檢查實(shí)作。 在下列範(fàn)例中,啟用類型的健康情況檢查會(huì)在其建構(gòu)函式中接受整數(shù)和字串:

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

若要登錄上述健康情況檢查,請(qǐng)使用傳遞為引數(shù)的整數(shù)和字串來(lái)呼叫 AddTypeActivatedCheck:

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

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

在 Program.cs 中,使用端點(diǎn) URL 或相對(duì)路徑以在端點(diǎn)建立器上呼叫 MapHealthChecks:

app.MapHealthChecks("/healthz");

需要主機(jī)

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

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

若要限制健康情況檢查端點(diǎn)只在特定連接埠上回應(yīng),請(qǐng)?jiān)?RequireHost 呼叫中指定連接埠。 此方式通常用於容器環(huán)境,以公開(kāi)監(jiān)控服務(wù)的連接埠:

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

若要防止未經(jīng)授權(quán)的用戶端詐騙連接埠,請(qǐng)呼叫 RequireAuthorization:

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

如需詳細(xì)資訊,請(qǐng)參閱具有 RequireHost 之路由中的主機(jī)比對(duì)。

需要授權(quán)

呼叫 RequireAuthorization,以在健康情況檢查要求端點(diǎn)上執(zhí)行授權(quán)中介軟體。 RequireAuthorization 多載接受一或多個(gè)授權(quán)原則。 如果未提供原則,則會(huì)使用預(yù)設(shè)授權(quán)原則:

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

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

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

健康狀態(tài)檢查選項(xiàng)

HealthCheckOptions 讓您有機(jī)會(huì)自訂健康狀態(tài)檢查行為:

篩選健康狀態(tài)檢查 自訂 HTTP 狀態(tài)碼 隱藏快取標(biāo)頭 自訂輸出

篩選健康狀態(tài)檢查

根據(jù)預(yù)設(shè),健康情況檢查中介軟體會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行健康狀態(tài)檢查子集,請(qǐng)對(duì) Predicate 選項(xiàng)提供傳回布林值的函式。

下列範(fàn)例會(huì)篩選健康情況檢查,以只執(zhí)行已標(biāo)記 sample 的檢查:

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

自訂 HTTP 狀態(tài)碼

您可以使用 ResultStatusCodes 來(lái)自訂健康狀態(tài)與 HTTP 狀態(tài)碼的對(duì)應(yīng)。 下列 StatusCodes 指派是中介軟體所使用的預(yù)設(shè)值。 變更狀態(tài)碼值,以符合您的需求:

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

隱藏快取標(biāo)頭

AllowCachingResponses 會(huì)控制健康情況檢查中介軟體是否將 HTTP 標(biāo)頭新增至探查回應(yīng),以防止回應(yīng)快取。 如果值為 false (預(yù)設(shè)),則中介軟體會(huì)設(shè)定或覆寫(xiě) Cache-Control、Expires 和 Pragma 標(biāo)頭,以防止回應(yīng)快取。 如果值為 true,則中介軟體不會(huì)修改回應(yīng)的快取標(biāo)頭:

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

自訂輸出

若要自訂健康情況檢查報(bào)告的輸出,請(qǐng)將 HealthCheckOptions.ResponseWriter 屬性設(shè)定為可寫(xiě)入回應(yīng)的委派:

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

預(yù)設(shè)委派會(huì)使用字串值 HealthReport.Status 寫(xiě)入基本純文字回應(yīng)。 下列自訂委派會(huì)使用 System.Text.Json來(lái)輸出自訂 JSON 回應(yīng):

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 傳回格式的內(nèi)建支援,因?yàn)榇烁袷绞悄x擇的監(jiān)控系統(tǒng)所特有。 視需要,自訂上述範(fàn)例中的回應(yīng)。 如需使用 System.Text.Json進(jìn)行 JSON 序列化的詳細(xì)資訊,請(qǐng)參閱 如何在 .NET 中序列化和還原序列化 JSON。

資料庫(kù)探查

健康狀態(tài)檢查可指定資料庫(kù)查詢以布林測(cè)試方式來(lái)執(zhí)行,藉此指出資料庫(kù)是否正?;貞?yīng)。

AspNetCore.Diagnostics.HealthChecks,一種適用於 ASP.NET Core 應(yīng)用程式的健康情況檢查程式庫(kù),包括針對(duì) SQL Server 資料庫(kù)所執(zhí)行的健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會(huì)對(duì)資料庫(kù)執(zhí)行 SELECT 1 查詢,以確認(rèn)資料庫(kù)連線狀況良好。

警告

使用查詢檢查資料庫(kù)連線時(shí),請(qǐng)選擇快速傳回的查詢。 查詢方法具有多載資料庫(kù)而降低其效能的風(fēng)險(xiǎn)。 在大部分情況下,不需要執(zhí)行測(cè)試查詢。 只要成功建立資料庫(kù)連線就已足夠。 如果您發(fā)現(xiàn)有必要執(zhí)行查詢,請(qǐng)選擇簡(jiǎn)單的 SELECT 查詢,例如 SELECT 1。

若要使用此 SQL Server 健康情況檢查,請(qǐng)包括 AspNetCore.HealthChecks.SqlServer NuGet 套件的套件參考。 下列範(fàn)例會(huì)登錄 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);

Entity Framework Core DbContext 探查

DbContext 檢查會(huì)確認(rèn)應(yīng)用程式是否可以與針對(duì) EF CoreDbContext 所設(shè)定的資料庫(kù)通訊。 應(yīng)用程式支援 DbContext 檢查:

使用 Entity Framework (EF) Core。 包括 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore NuGet 套件的套件參考。

AddDbContextCheck 會(huì)登錄 DbContext 的健康狀態(tài)檢查。 DbContext 會(huì)以 TContext 形式提供給方法。 多載可用來(lái)設(shè)定失敗狀態(tài)、標(biāo)籤和自訂測(cè)試查詢。

預(yù)設(shè)情況:

DbContextHealthCheck 會(huì)呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態(tài)時(shí)所要執(zhí)行的作業(yè)。 健康狀態(tài)檢查的名稱是 TContext 類型的名稱。

下列範(fàn)例會(huì)登錄 DbContext 和相關(guān)聯(lián)的 DbContextHealthCheck:

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

個(gè)別的整備度與活躍度探查

在某些裝載案例中,會(huì)使用一組健康情況檢查來(lái)區(qū)分兩個(gè)應(yīng)用程式狀態(tài):

「整備」指出應(yīng)用程式是否正在正常執(zhí)行,但尚未準(zhǔn)備好接收要求。 「活躍度」指出應(yīng)用程式是否已當(dāng)機(jī),而且必須重新予以啟動(dòng)。

請(qǐng)考慮下列範(fàn)例:應(yīng)用程式在準(zhǔn)備好處理要求之前必須下載大型設(shè)定檔。 如果初始下載失敗,則我們不想要重新啟動(dòng)應(yīng)用程式,因?yàn)閼?yīng)用程式可以重試下載檔案數(shù)次。 我們使用「活躍度探查」來(lái)描述處理序的活躍度,而不會(huì)執(zhí)行其他檢查。 我們也想要防止在設(shè)定檔下載成功之前將要求傳送至應(yīng)用程式。 除非下載成功,而且應(yīng)用程式準(zhǔn)備好接收要求,否則我們會(huì)使用「整備度探查」來(lái)指出「尚未就緒」?fàn)顟B(tài)。

下列背景工作會(huì)模擬大約需要 15 秒的啟動(dòng)處理序。 完成後,工作會(huì)將 StartupHealthCheck.StartupCompleted 屬性設(shè)定為 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 會(huì)報(bào)告長(zhǎng)時(shí)間執(zhí)行的啟動(dòng)工作完成,並公開(kāi)背景服務(wù)所設(shè)定的 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.")); } }

健康狀態(tài)檢查是 Program.cs 中使用 AddCheck 隨託管服務(wù)一起登錄。 因?yàn)樗b載服務(wù)必須在健康情況檢查上設(shè)定此屬性,所以也會(huì)在服務(wù)容器中將健康情況檢查登錄為單一資料庫(kù):

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

若要建立兩個(gè)不同的健康情況檢查端點(diǎn),請(qǐng)呼叫 MapHealthChecks 兩次:

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

上述範(fàn)例會(huì)建立下列健康情況檢查端點(diǎn):

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

啟動(dòng)工作完成之前,/healthz/ready 端點(diǎn)會(huì)回報(bào) Unhealthy 狀態(tài)。 啟動(dòng)工作完成之後,此端點(diǎn)會(huì)回報(bào) Healthy 狀態(tài)。 /healthz/live 端點(diǎn)會(huì)排除所有檢查,並將所有呼叫的狀態(tài)都回報(bào)為 Healthy。

Kubernetes 範(fàn)例

使用個(gè)別的整備度與活躍度檢查在 Kubernetes 之類的環(huán)境中很有用。 在 Kubernetes 中,應(yīng)用程式可能需要先執(zhí)行耗時(shí)的啟動(dòng)工作,才能接受要求 (例如基礎(chǔ)資料庫(kù)可用性測(cè)試)。 使用個(gè)別的檢查可讓協(xié)調(diào)器區(qū)分應(yīng)用程式是否為正常運(yùn)作但尚未準(zhǔn)備好,或應(yīng)用程式是否無(wú)法啟動(dòng)。 如需 Kubernetes 中整備度與活躍度探查的詳細(xì)資訊,請(qǐng)參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設(shè)定活躍度與整備度探查)。

下列範(fàn)例示範(fàn) Kubernetes 整備度探查組態(tài):

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

發(fā)佈健康狀態(tài)檢查程式庫(kù)

若要發(fā)佈健康狀態(tài)檢查作為程式庫(kù):

寫(xiě)入健康狀態(tài)檢查,將 IHealthCheck 介面當(dāng)做獨(dú)立類別來(lái)實(shí)作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項(xiàng)來(lái)存取組態(tài)資料。

使用取用應(yīng)用程式在其 Program.cs 方法中呼叫的參數(shù),來(lái)寫(xiě)入延伸模組。 請(qǐng)考慮下列範(fàn)例健康情況檢查,而此檢查接受 arg1 和 arg2 作為建構(gòu)函式參數(shù):

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

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

arg1:健康情況檢查的整數(shù)資料點(diǎn)。 arg2:健康情況檢查的字串引數(shù)。 name:選用的健康情況檢查名稱。 如果 null,則會(huì)使用預(yù)設(shè)值。 failureStatus:選用的 HealthStatus,其回報(bào)失敗狀態(tài)。 如果為 null,則會(huì)使用 HealthStatus.Unhealthy。 tags:標(biāo)記的選用 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)); } }

健康狀態(tài)檢查發(fā)行者

當(dāng) IHealthCheckPublisher 新增至服務(wù)容器時(shí),健康狀態(tài)檢查系統(tǒng)會(huì)定期執(zhí)行健康狀態(tài)檢查,並呼叫 PublishAsync 傳回結(jié)果。 此處理序適用於推送型健康情況監(jiān)控系統(tǒng)案例,而此案例預(yù)期每個(gè)處理序都會(huì)定期呼叫監(jiān)控系統(tǒng)來(lái)判斷健康情況。

HealthCheckPublisherOptions 可讓您設(shè)定:

Delay:初始延遲會(huì)在應(yīng)用程式啟動(dòng)之後且執(zhí)行 IHealthCheckPublisher 執(zhí)行個(gè)體之前套用。 啟動(dòng)後就會(huì)套用延遲,但不會(huì)套用至後面的反覆項(xiàng)目。 預(yù)設(shè)值是五秒鐘。 Period:IHealthCheckPublisher 執(zhí)行的期間。 預(yù)設(shè)值為 30 秒。 Predicate:如果 Predicate 為 null (預(yù)設(shè)),則健康情況檢查發(fā)行者服務(wù)會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行一部分的健康狀態(tài)檢查,請(qǐng)?zhí)峁┛珊Y選該組檢查的函式。 每個(gè)期間都會(huì)評(píng)估該述詞。 Timeout:執(zhí)行所有 IHealthCheckPublisher 執(zhí)行個(gè)體之健康情況檢查的逾時(shí)。 若要在沒(méi)有逾時(shí)的情況下執(zhí)行,請(qǐng)使用 InfiniteTimeSpan。 預(yù)設(shè)值為 30 秒。

下列範(fàn)例示範(fàn)健康情況發(fā)行者的配置:

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

HealthCheckPublisherOptions 類別提供屬性來(lái)設(shè)定健康情況檢查發(fā)行者的行為。

下列範(fàn)例會(huì)將健康情況檢查發(fā)行者登錄為單一資料庫(kù),並設(shè)定 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:

包括數(shù)個(gè)系統(tǒng)的發(fā)行者,包括 Application Insights。 受 Microsoft 維護(hù)或支援。

個(gè)別的 HealthChecks

Delay 和 Period 可以在每個(gè) HealthCheckRegistration 上個(gè)別設(shè)定。 當(dāng)您想要以與 HealthCheckPublisherOptions 中所設(shè)定的期間不同的速率執(zhí)行一些健康情況檢查時(shí),這非常有用。

下列程式碼會(huì)設(shè)定 SampleHealthCheck1 的 Delay 和 Period:

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();

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

您可以使用相依性插入來(lái)取用健康情況檢查類別內(nèi)特定 Type 的執(zhí)行個(gè)體。 相依性插入適用於將選項(xiàng)或全域設(shè)定插入至健康情況檢查。 使用相依性插入「不」是設(shè)定健康情況檢查的常見(jiàn)案例。 通常,每個(gè)健康情況檢查都是專屬於實(shí)際測(cè)試,並且使用 IHealthChecksBuilder 擴(kuò)充方法進(jìn)行設(shè)定。

下列範(fàn)例顯示可透過(guò)相依性插入來(lái)擷取設(shè)定物件的範(fàn)例健康情況檢查:

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 和健康情況檢查需要新增至服務(wù)容器:

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 會(huì)登錄中介軟體來(lái)處理中介軟體管線中的健康情況檢查要求。 MapHealthChecks 會(huì)登錄健康情況檢查端點(diǎn)。 端點(diǎn)會(huì)與應(yīng)用程式中的其他端點(diǎn)進(jìn)行比對(duì)和執(zhí)行。

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

UseHealthChecks:

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

MapHealthChecks 允許:

呼叫 ShortCircuit,以在要求符合健康情況檢查端點(diǎn)時(shí)終止管線。 例如: app.MapHealthChecks("/healthz").ShortCircuit(); 。 如需詳細(xì)資訊,請(qǐng)參閱路由之後尋找中介軟體的最短路徑。 對(duì)應(yīng)特定路由或端點(diǎn)以進(jìn)行健康情況檢查。 自訂可存取健康情況檢查端點(diǎn)的 URL 或路徑。 使用不同的路由或設(shè)定來(lái)對(duì)應(yīng)多個(gè)健康情況檢查端點(diǎn)。 多個(gè)端點(diǎn)支援: 針對(duì)不同類型的健康情況檢查或元件啟用不同的端點(diǎn)。 用來(lái)區(qū)分應(yīng)用程式健康情況的不同層面,或?qū)⑻囟ㄔO(shè)定套用至健康情況檢查的子集。 原始程式碼

其他資源

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

ASP.NET Core 提供健康情況檢查中介軟體和程式庫(kù),用來(lái)報(bào)告應(yīng)用程式基礎(chǔ)結(jié)構(gòu)元件的健康情況。

應(yīng)用程式會(huì)將健康狀態(tài)檢查公開(kāi)為 HTTP 端點(diǎn)。 您可以針對(duì)各種即時(shí)監(jiān)控案例來(lái)設(shè)定健康情況檢查端點(diǎn):

容器協(xié)調(diào)器和負(fù)載平衡器可以使用健康狀態(tài)探查,來(lái)檢查應(yīng)用程式的狀態(tài)。 例如,容器協(xié)調(diào)器可能會(huì)暫停輪流部署或重新啟動(dòng)容器,來(lái)回應(yīng)失敗的健康狀態(tài)檢查。 負(fù)載平衡器可能會(huì)將流量從失敗的執(zhí)行個(gè)體路由傳送至狀況良好的執(zhí)行個(gè)體,來(lái)回應(yīng)狀況不良的應(yīng)用程式。 您可以監(jiān)控所使用記憶體、磁碟及其他實(shí)體伺服器資源的健康狀態(tài)。 健康狀態(tài)檢查可以測(cè)試應(yīng)用程式的相依性 (例如資料庫(kù)和外部服務(wù)端點(diǎn)),確認(rèn)其是否可用且正常運(yùn)作。

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

範(fàn)例應(yīng)用程式包括本文中所述的案例範(fàn)例。 若要在指定的案例中執(zhí)行範(fàn)例應(yīng)用程式,請(qǐng)?jiān)诿顨又惺褂脕?lái)自專案資料夾的 dotnet run 命令。 如需如何使用範(fàn)例應(yīng)用程式的詳細(xì)資料,請(qǐng)參閱範(fàn)例應(yīng)用程式的 README.md 檔案和本文中的案例描述。

必要條件

健康情況檢查通常會(huì)與外部監(jiān)控服務(wù)或容器協(xié)調(diào)器搭配使用,來(lái)檢查應(yīng)用程式的狀態(tài)。 將健康狀態(tài)檢查新增至應(yīng)用程式之前,請(qǐng)決定要使用的監(jiān)控系統(tǒng)。 監(jiān)控系統(tǒng)會(huì)指定要建立哪些健康狀態(tài)檢查類型,以及如何設(shè)定其端點(diǎn)。

ASP.NET Core 應(yīng)用程式會(huì)隱含參考 Microsoft.AspNetCore.Diagnostics.HealthChecks 套件。 若要使用 Entity Framework Core 來(lái)執(zhí)行健康情況檢查,請(qǐng)新增 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 套件的參考。

範(fàn)例應(yīng)用程式提供啟動(dòng)程式碼,來(lái)示範(fàn)數(shù)個(gè)案例的健康狀態(tài)檢查。 資料庫(kù)探查案例使用 AspNetCore.Diagnostics.HealthChecks 來(lái)檢查資料庫(kù)連線的健康情況。 DbContext 探查案例使用 EF CoreDbContext 來(lái)檢查資料庫(kù)。 為了探索資料庫(kù)案例,範(fàn)例應(yīng)用程式會(huì):

建立資料庫(kù),並在 appsettings.json 檔案中提供其連接字串。 在其專案檔中具有下列套件參考: AspNetCore.HealthChecks.SqlServer Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore

另一個(gè)健康狀態(tài)檢查案例示範(fàn)如何將健康狀態(tài)檢查篩選至管理連接埠。 範(fàn)例應(yīng)用程式需要您建立 Properties/launchSettings.json 檔案,而此檔案包括管理 URL 和管理連接埠。 如需詳細(xì)資訊,請(qǐng)參閱依連接埠篩選一節(jié)。

基本健康狀態(tài)探查

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

基本設(shè)定會(huì)登錄健康情況檢查服務(wù),並呼叫健康情況檢查中介軟體以在具有健康情況回應(yīng)的 URL 端點(diǎn)做出回應(yīng)。 預(yù)設(shè)並未登錄特定健康狀態(tài)檢查來(lái)測(cè)試任何特定相依性或子系統(tǒng)。 如果應(yīng)用程式可以在健康情況端點(diǎn) URL 做出回應(yīng),則視為狀況良好。 預(yù)設(shè)回應(yīng)寫(xiě)入器會(huì)將狀態(tài) (HealthStatus) 以純文字回應(yīng)形式回寫(xiě)至用戶端,指出 HealthStatus.Healthy、HealthStatus.Degraded 或 HealthStatus.Unhealthy 狀態(tài)。

在 Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態(tài)檢查服務(wù)。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點(diǎn)。

在範(fàn)例應(yīng)用程式中,是在 /health (BasicStartup.cs) 建立健康情況檢查端點(diǎn):

public class BasicStartup { public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); } }

若要使用範(fàn)例應(yīng)用程式執(zhí)行基本組態(tài)案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario basic

Docker 範(fàn)例

Docker 提供內(nèi)建 HEALTHCHECK 指示詞,可用來(lái)檢查使用基本健康狀態(tài)檢查組態(tài)的應(yīng)用程式狀態(tài):

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

建立健康狀態(tài)檢查

健康狀態(tài)檢查是藉由實(shí)作 IHealthCheck 介面來(lái)建立。 CheckHealthAsync 方法會(huì)傳回指出狀態(tài)為 Healthy、Degraded 或 Unhealthy 的 HealthCheckResult。 結(jié)果會(huì)寫(xiě)成具有可設(shè)定狀態(tài)碼的純文字回應(yīng) (健康狀態(tài)檢查選項(xiàng)一節(jié)中將說(shuō)明如何進(jìn)行組態(tài))。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

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

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 在檢查期間擲回例外狀況,則會(huì)傳回其 HealthReportEntry.Status 設(shè)定為 FailureStatus 的新 HealthReportEntry (這由 AddCheck 所定義) (請(qǐng)參閱登錄健康情況檢查服務(wù)小節(jié)),並包括最初造成檢查失敗的內(nèi)部例外狀況。 Description 會(huì)設(shè)定為例外狀況的訊息。

登錄健康狀態(tài)檢查服務(wù)

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

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

下列範(fàn)例中所顯示的 AddCheck 多載會(huì)設(shè)定在健康狀態(tài)檢查報(bào)告失敗時(shí)所要報(bào)告的失敗狀態(tài) (HealthStatus)。 如果將失敗狀態(tài)設(shè)定為 null (預(yù)設(shè)),則會(huì)報(bào)告 HealthStatus.Unhealthy。 此多載對(duì)程式庫(kù)作者很有用。若健康狀態(tài)檢查實(shí)作採(cǎi)用此設(shè)定,則當(dāng)健康狀態(tài)檢查失敗時(shí),應(yīng)用程式就會(huì)強(qiáng)制程式庫(kù)指出失敗狀態(tài)。

您可以使用「標(biāo)籤」來(lái)篩選健康狀態(tài)檢查 (篩選健康狀態(tài)檢查一節(jié)中將進(jìn)一步說(shuō)明)。

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

AddCheck 也可以執(zhí)行匿名函式。 在下列範(fàn)例中,健康狀態(tài)檢查名稱指定為 Example,且檢查一律會(huì)傳回狀況良好狀態(tài):

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

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

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) { ... } }

使用傳遞至實(shí)作的整數(shù)和字串來(lái)呼叫 AddTypeActivatedCheck,以登錄 TestHealthCheckWithArgs:

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

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

在 Startup.Configure 中,使用端點(diǎn) URL 或相對(duì)路徑以在端點(diǎn)建立器上呼叫 MapHealthChecks:

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

需要主機(jī)

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

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

如需詳細(xì)資訊,請(qǐng)參閱依連接埠篩選一節(jié)。

需要授權(quán)

呼叫 RequireAuthorization,以在健康情況檢查要求端點(diǎn)上執(zhí)行授權(quán)中介軟體。 RequireAuthorization 多載接受一或多個(gè)授權(quán)原則。 如果未提供原則,則會(huì)使用預(yù)設(shè)授權(quán)原則。

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

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

雖然從瀏覽器手動(dòng)執(zhí)行健康情況檢查不是常見(jiàn)使用案例,但是您可以在健康情況檢查端點(diǎn)上呼叫 RequireCors,以啟用 CORS 中介軟體。 RequireCors 多載接受 CORS 原則建立器委派 (CorsPolicyBuilder) 或原則名稱。 如果未提供原則,則會(huì)使用預(yù)設(shè) CORS 原則。 如需詳細(xì)資訊,請(qǐng)參閱在 ASP.NET Core 中啟用跨原始來(lái)源要求 (CORS)。

健康狀態(tài)檢查選項(xiàng)

HealthCheckOptions 讓您有機(jī)會(huì)自訂健康狀態(tài)檢查行為:

篩選健康狀態(tài)檢查 自訂 HTTP 狀態(tài)碼 隱藏快取標(biāo)頭 自訂輸出

篩選健康狀態(tài)檢查

根據(jù)預(yù)設(shè),健康情況檢查中介軟體會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行健康狀態(tài)檢查子集,請(qǐng)對(duì) Predicate 選項(xiàng)提供傳回布林值的函式。 在下列範(fàn)例中,會(huì)依函式條件陳述式中的標(biāo)籤 (bar_tag) 篩選出 Bar 健康狀態(tài)檢查。只有在健康狀態(tài)檢查的 Tags 屬性符合 foo_tag 或 baz_tag 時(shí),才傳回 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 會(huì)篩選出「橫條圖」健康情況檢查。 只有 Foo 和 Baz 才能執(zhí)行:

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

自訂 HTTP 狀態(tài)碼

您可以使用 ResultStatusCodes 來(lái)自訂健康狀態(tài)與 HTTP 狀態(tài)碼的對(duì)應(yīng)。 下列 StatusCodes 指派是中介軟體所使用的預(yù)設(shè)值。 請(qǐng)變更狀態(tài)碼值以符合您的需求。

在 Startup.Configure 中:

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

隱藏快取標(biāo)頭

AllowCachingResponses 會(huì)控制健康情況檢查中介軟體是否將 HTTP 標(biāo)頭新增至探查回應(yīng),以防止回應(yīng)快取。 如果值為 false (預(yù)設(shè)),則中介軟體會(huì)設(shè)定或覆寫(xiě) Cache-Control、Expires 和 Pragma 標(biāo)頭,以防止回應(yīng)快取。 如果值為 true,則中介軟體不會(huì)修改回應(yīng)的快取標(biāo)頭。

在 Startup.Configure 中:

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

自訂輸出

在 Startup.Configure 中,將 HealthCheckOptions.ResponseWriter 選項(xiàng)設(shè)定為撰寫(xiě)回應(yīng)的委派:

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

預(yù)設(shè)委派會(huì)使用字串值 HealthReport.Status 寫(xiě)入基本純文字回應(yīng)。 下列自訂委派會(huì)輸出自訂 JSON 回應(yīng)。

範(fàn)例應(yīng)用程式中的第一個(gè)範(fàn)例示範(fàn)如何使用 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); } }

第二個(gè)範(fàn)例示範(fàn)如何使用 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)); }

在範(fàn)例應(yīng)用程式中,註解化 CustomWriterStartup.cs 中的 SYSTEM_TEXT_JSON 前置處理器指示詞,以啟用 WriteResponse 的 Newtonsoft.Json 版本。

健康情況檢查 API 未提供複雜 JSON 傳回格式的內(nèi)建支援,因?yàn)榇烁袷绞悄x擇的監(jiān)控系統(tǒng)所特有。 視需要,自訂上述範(fàn)例中的回應(yīng)。 如需使用 System.Text.Json進(jìn)行 JSON 序列化的詳細(xì)資訊,請(qǐng)參閱 如何在 .NET 中序列化和還原序列化 JSON。

資料庫(kù)探查

健康狀態(tài)檢查可指定資料庫(kù)查詢以布林測(cè)試方式來(lái)執(zhí)行,藉此指出資料庫(kù)是否正?;貞?yīng)。

範(fàn)例應(yīng)用程式使用 AspNetCore.Diagnostics.HealthChecks (一種適用於 ASP.NET Core 應(yīng)用程式的健康情況檢查程式庫(kù)),以在 SQL Server 資料庫(kù)上執(zhí)行健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會(huì)對(duì)資料庫(kù)執(zhí)行 SELECT 1 查詢,以確認(rèn)資料庫(kù)連線狀況良好。

警告

使用查詢檢查資料庫(kù)連線時(shí),請(qǐng)選擇快速傳回的查詢。 查詢方法具有多載資料庫(kù)而降低其效能的風(fēng)險(xiǎn)。 在大部分情況下,不需要執(zhí)行測(cè)試查詢。 只要成功建立資料庫(kù)連線就已足夠。 如果您發(fā)現(xiàn)有必要執(zhí)行查詢,請(qǐng)選擇簡(jiǎn)單的 SELECT 查詢,例如 SELECT 1。

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

在範(fàn)例應(yīng)用程式的 appsettings.json 檔案中,提供有效的資料庫(kù)連接字串。 應(yīng)用程式使用名為 HealthCheckSample 的 SQL Server 資料庫(kù):

{ "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 登錄健康狀態(tài)檢查服務(wù)。 範(fàn)例應(yīng)用程式會(huì)使用資料庫(kù)連接字串 (DbHealthStartup.cs) 來(lái)呼叫 AddSqlServer 方法:

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

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks:

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

若要使用範(fàn)例應(yīng)用程式執(zhí)行資料庫(kù)探查案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario db

Entity Framework Core DbContext 探查

DbContext 檢查會(huì)確認(rèn)應(yīng)用程式是否可以與針對(duì) EF CoreDbContext 所設(shè)定的資料庫(kù)通訊。 應(yīng)用程式支援 DbContext 檢查:

使用 Entity Framework (EF) Core。 包括 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 的套件參考。

AddDbContextCheck<TContext> 會(huì)登錄 DbContext 的健康狀態(tài)檢查。 DbContext 會(huì)以 TContext 形式提供給方法。 多載可用來(lái)設(shè)定失敗狀態(tài)、標(biāo)籤和自訂測(cè)試查詢。

預(yù)設(shè)情況:

DbContextHealthCheck 會(huì)呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態(tài)時(shí)所要執(zhí)行的作業(yè)。 健康狀態(tài)檢查的名稱是 TContext 類型的名稱。

在範(fàn)例應(yīng)用程式中,會(huì)將 AppDbContext 提供給 AddDbContextCheck,並在 Startup.ConfigureServices 中登錄為服務(wù) (DbContextHealthStartup.cs):

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

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks:

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

若要使用範(fàn)例應(yīng)用程式來(lái)執(zhí)行 DbContext 探查案例,請(qǐng)確認(rèn) SQL Server 執(zhí)行個(gè)體中沒(méi)有連接字串所指定的資料庫(kù)。 如果資料庫(kù)存在,請(qǐng)予以刪除。

在命令殼層中執(zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario dbcontext

在應(yīng)用程式執(zhí)行之後,對(duì)瀏覽器中的 /health 端點(diǎn)提出要求來(lái)檢查健康狀態(tài)。 資料庫(kù)和 AppDbContext 不存在,因此應(yīng)用程式會(huì)提供下列回應(yīng):

Unhealthy

觸發(fā)範(fàn)例應(yīng)用程式以建立資料庫(kù)。 對(duì) /createdatabase 提出要求。 應(yīng)用程式會(huì)回應(yīng):

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

對(duì) /health 端點(diǎn)提出要求。 資料庫(kù)和內(nèi)容存在,因此應(yīng)用程式會(huì)回應(yīng):

Healthy

觸發(fā)範(fàn)例應(yīng)用程式以刪除資料庫(kù)。 對(duì) /deletedatabase 提出要求。 應(yīng)用程式會(huì)回應(yīng):

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

對(duì) /health 端點(diǎn)提出要求。 應(yīng)用程式會(huì)提供狀況不良回應(yīng):

Unhealthy

個(gè)別的整備度與活躍度探查

在某些裝載案例中,會(huì)使用一組健康情況檢查來(lái)區(qū)分兩個(gè)應(yīng)用程式狀態(tài):

「整備」指出應(yīng)用程式是否正在正常執(zhí)行,但尚未準(zhǔn)備好接收要求。 「活躍度」指出應(yīng)用程式是否已當(dāng)機(jī),而且必須重新予以啟動(dòng)。

請(qǐng)考慮下列範(fàn)例:應(yīng)用程式在準(zhǔn)備好處理要求之前必須下載大型設(shè)定檔。 如果初始下載失敗,則我們不想要重新啟動(dòng)應(yīng)用程式,因?yàn)閼?yīng)用程式可以重試下載檔案數(shù)次。 我們使用「活躍度探查」來(lái)描述處理序的活躍度,而不會(huì)執(zhí)行其他檢查。 我們也想要防止在設(shè)定檔下載成功之前將要求傳送至應(yīng)用程式。 除非下載成功,而且應(yīng)用程式準(zhǔn)備好接收要求,否則我們會(huì)使用「整備度探查」來(lái)指出「尚未就緒」?fàn)顟B(tài)。

範(fàn)例應(yīng)用程式包含健康狀態(tài)檢查,會(huì)在託管服務(wù)中長(zhǎng)時(shí)間執(zhí)行的啟動(dòng)工作完成時(shí)回報(bào)。 StartupHostedServiceHealthCheck 會(huì)公開(kāi) StartupTaskCompleted 屬性,而裝載的服務(wù)可以在其長(zhǎng)時(shí)間執(zhí)行的工作完成時(shí),將此屬性設(shè)定為 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.")); } }

裝載的服務(wù) (Services/StartupHostedService) 會(huì)啟動(dòng)長(zhǎng)時(shí)間執(zhí)行的背景工作。 工作完成時(shí),StartupHostedServiceHealthCheck.StartupTaskCompleted 會(huì)設(shè)定為 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() { } }

健康狀態(tài)檢查是 Startup.ConfigureServices 中使用 AddCheck 隨託管服務(wù)一起登錄。 因?yàn)樗b載服務(wù)必須在健康情況檢查上設(shè)定此屬性,所以也會(huì)在服務(wù)容器中登錄健康情況檢查 (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>();

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 在範(fàn)例應(yīng)用程式中,是在下列位置建立健康情況檢查端點(diǎn):

/health/ready 用於整備檢查。 整備度檢查使用 ready 標(biāo)籤來(lái)篩選健康狀態(tài)檢查。 /health/live 用於活躍度檢查。 活躍度檢查是在 HealthCheckOptions.Predicate 中傳回 false 來(lái)篩選出 StartupHostedServiceHealthCheck (如需詳細(xì)資訊,請(qǐng)參閱篩選健康情況檢查)

在下列範(fàn)例程式碼中:

整備檢查會(huì)使用具有「就緒」標(biāo)記的所有已登錄檢查。 Predicate 會(huì)排除所有檢查,並傳回 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 }); }

若要使用範(fàn)例應(yīng)用程式執(zhí)行整備度/活躍度組態(tài)案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario liveness

在瀏覽器中,瀏覽 /health/ready 數(shù)次,直到經(jīng)過(guò) 15 秒。 健康狀態(tài)檢查報(bào)告前 15 秒為 Unhealthy。 15 秒之後,端點(diǎn)會(huì)報(bào)告 Healthy,以反映託管服務(wù)長(zhǎng)時(shí)間執(zhí)行的工作已完成。

此範(fàn)例也會(huì)建立一個(gè)以兩秒延遲執(zhí)行第一次整備檢查的「健康情況檢查發(fā)行者」(IHealthCheckPublisher 實(shí)作)。 如需詳細(xì)資訊,請(qǐng)參閱健康狀態(tài)檢查發(fā)行者一節(jié)。

Kubernetes 範(fàn)例

使用個(gè)別的整備度與活躍度檢查在 Kubernetes 之類的環(huán)境中很有用。 在 Kubernetes 中,應(yīng)用程式可能需要先執(zhí)行耗時(shí)的啟動(dòng)工作,才能接受要求 (例如基礎(chǔ)資料庫(kù)可用性測(cè)試)。 使用個(gè)別的檢查可讓協(xié)調(diào)器區(qū)分應(yīng)用程式是否為正常運(yùn)作但尚未準(zhǔn)備好,或應(yīng)用程式是否無(wú)法啟動(dòng)。 如需 Kubernetes 中整備度與活躍度探查的詳細(xì)資訊,請(qǐng)參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設(shè)定活躍度與整備度探查)。

下列範(fàn)例示範(fàn) Kubernetes 整備度探查組態(tài):

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

透過(guò)自訂回應(yīng)寫(xiě)入器的計(jì)量型探查

範(fàn)例應(yīng)用程式示範(fàn)透過(guò)自訂回應(yīng)寫(xiě)入器的記憶體健康狀態(tài)檢查。

如果應(yīng)用程式使用超過(guò)指定的記憶體閾值 (在範(fàn)例應(yīng)用程式中為 1 GB),MemoryHealthCheck 會(huì)報(bào)告降級(jí)的狀態(tài)。 HealthCheckResult 包括應(yīng)用程式的記憶體回收行程 (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 登錄健康狀態(tài)檢查服務(wù)。 MemoryHealthCheck 會(huì)登錄為服務(wù),而不是將健康狀態(tài)檢查傳遞至 AddCheck 以啟用檢查。 所有 IHealthCheck 登錄的服務(wù)都可供健康狀態(tài)檢查服務(wù)和中介軟體使用。 建議將健康狀態(tài)檢查服務(wù)登錄為單一服務(wù)。

在範(fàn)例應(yīng)用程式的 CustomWriterStartup.cs 中:

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

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 當(dāng)健康狀態(tài)檢查執(zhí)行時(shí),會(huì)將 WriteResponse 委派提供給 ResponseWriter 屬性以輸出自訂 JSON 回應(yīng):

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

WriteResponse 委派會(huì)將 CompositeHealthCheckResult 格式化為 JSON 物件,並產(chǎn)生健康情況檢查回應(yīng)的 JSON 輸出。 如需詳細(xì)資訊,請(qǐng)參閱自訂輸出小節(jié)。

若要使用範(fàn)例應(yīng)用程式透過(guò)自訂回應(yīng)寫(xiě)入器輸出執(zhí)行計(jì)量型探查,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario writer

依連接埠篩選

使用 URL 模式以在 MapHealthChecks 上呼叫 RequireHost,而此模式指定連接埠來(lái)限制針對(duì)所指定連接埠的健康情況檢查要求。 此方式通常用於容器環(huán)境,以公開(kāi)監(jiān)控服務(wù)的連接埠。

範(fàn)例應(yīng)用程式使用環(huán)境變數(shù)組態(tài)提供者來(lái)設(shè)定連接埠。 連接埠是在 launchSettings.json 檔案中設(shè)定,並透過(guò)環(huán)境變數(shù)傳遞至設(shè)定提供者。 您也必須將伺服器設(shè)定為在管理連接埠上接聽(tīng)要求。

若要使用範(fàn)例應(yīng)用程式來(lái)示範(fàn)管理連接埠設(shè)定,請(qǐng)?jiān)?Properties 資料夾中建立 launchSettings.json 檔案。

範(fàn)例應(yīng)用程式中的下列 Properties/launchSettings.json 檔案未包括在範(fàn)例應(yīng)用程式的專案檔中,而且必須手動(dòng)予以建立:

{ "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 登錄健康狀態(tài)檢查服務(wù)。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點(diǎn)。

在範(fàn)例應(yīng)用程式中,對(duì) Startup.Configure 中端點(diǎn)的 RequireHost 呼叫指定設(shè)定管理連接埠:

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

在範(fàn)例應(yīng)用程式的 Startup.Configure 中,建立端點(diǎn)。 在下列範(fàn)例程式碼中:

整備檢查會(huì)使用具有「就緒」標(biāo)記的所有已登錄檢查。 Predicate 會(huì)排除所有檢查,並傳回 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 }); }

注意

您可以在程式碼中明確設(shè)定管理連接埠,以避免在範(fàn)例應(yīng)用程式中建立 launchSettings.json 檔案。 在 HostBuilder 建立所在的 Program.cs 中,新增 ListenAnyIP 呼叫,並提供應(yīng)用程式的管理連接埠端點(diǎn)。 在 ManagementPortStartup.cs 的 Configure 中,使用 RequireHost 來(lái)指定管理連接埠:

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

若要使用範(fàn)例應(yīng)用程式執(zhí)行管理連接埠組態(tài)案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario port

發(fā)佈健康狀態(tài)檢查程式庫(kù)

若要發(fā)佈健康狀態(tài)檢查作為程式庫(kù):

寫(xiě)入健康狀態(tài)檢查,將 IHealthCheck 介面當(dāng)做獨(dú)立類別來(lái)實(shí)作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項(xiàng)來(lái)存取組態(tài)資料。

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

data1 和 data2 用於此方法,以執(zhí)行探查的健康情況檢查邏輯。 已處理 AccessViolationException。

發(fā)生 AccessViolationException 時(shí),會(huì)使用 HealthCheckResult 來(lái)傳回 FailureStatus,以允許使用者設(shè)定健康情況檢查失敗狀態(tài)。

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

使用取用應(yīng)用程式在其 Startup.Configure 方法中呼叫的參數(shù),來(lái)寫(xiě)入延伸模組。 在下列範(fàn)例中,假設(shè)健康狀態(tài)檢查方法簽章如下:

ExampleHealthCheck(string, string, int )

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

健康狀態(tài)檢查名稱 (name)。 如果為 null,則會(huì)使用 example_health_check。 健康狀態(tài)檢查的字串資料點(diǎn) (data1)。 健康狀態(tài)檢查的整數(shù)資料點(diǎn) (data2)。 如果為 null,則會(huì)使用 1。 失敗狀態(tài) (HealthStatus)。 預(yù)設(shè)值為 null。 如果為 null,則會(huì)報(bào)告失敗狀態(tài)為 HealthStatus.Unhealthy。 標(biāo)籤 (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)); } }

健康狀態(tài)檢查發(fā)行者

當(dāng) IHealthCheckPublisher 新增至服務(wù)容器時(shí),健康狀態(tài)檢查系統(tǒng)會(huì)定期執(zhí)行健康狀態(tài)檢查,並呼叫 PublishAsync 傳回結(jié)果。 這對(duì)推送型健康狀態(tài)監(jiān)控系統(tǒng)案例很有用,其預(yù)期每個(gè)處理序會(huì)定期呼叫監(jiān)控系統(tǒng)來(lái)判斷健康狀態(tài)。

IHealthCheckPublisher 介面有單一方法:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions 可讓您設(shè)定:

Delay:初始延遲會(huì)在應(yīng)用程式啟動(dòng)之後且執(zhí)行 IHealthCheckPublisher 執(zhí)行個(gè)體之前套用。 在啟動(dòng)後就會(huì)套用延遲,但不會(huì)套用至後續(xù)的反覆項(xiàng)目。 預(yù)設(shè)值是五秒鐘。 Period:IHealthCheckPublisher 執(zhí)行的期間。 預(yù)設(shè)值為 30 秒。 Predicate:如果 Predicate 為 null (預(yù)設(shè)),則健康情況檢查發(fā)行者服務(wù)會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行一部分的健康狀態(tài)檢查,請(qǐng)?zhí)峁┛珊Y選該組檢查的函式。 每個(gè)期間都會(huì)評(píng)估該述詞。 Timeout:執(zhí)行所有 IHealthCheckPublisher 執(zhí)行個(gè)體之健康情況檢查的逾時(shí)。 若要在沒(méi)有逾時(shí)的情況下執(zhí)行,請(qǐng)使用 InfiniteTimeSpan。 預(yù)設(shè)值為 30 秒。

在範(fàn)例應(yīng)用程式中,ReadinessPublisher 是一個(gè) IHealthCheckPublisher 實(shí)作。 在下列記錄層級(jí),會(huì)記錄每個(gè)檢查的健康情況檢查狀態(tài):

如果健康情況檢查狀態(tài)為 Healthy,則為資訊 (LogInformation)。 如果狀態(tài)為 Degraded 或 Unhealthy,則為錯(cuò)誤 (LogError)。

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; } }

在範(fàn)例應(yīng)用程式的 LivenessProbeStartup 範(fàn)例中,StartupHostedService 整備檢查具有 2 秒的啟動(dòng)延遲,且每 30 秒會(huì)執(zhí)行一次檢查。 為了啟用 IHealthCheckPublisher 實(shí)作,此範(fàn)例會(huì)在相依性插入 (DI) 容器中將 ReadinessPublisher 註冊(cè)為單一服務(wù):

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>();

利用 MapWhen 限制健康情況檢查

使用 MapWhen 來(lái)有條件地將健康情況檢查端點(diǎn)的要求管線分支。

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

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

如需詳細(xì)資訊,請(qǐng)參閱 ASP.NET Core 中介軟體。

ASP.NET Core 提供健康情況檢查中介軟體和程式庫(kù),用來(lái)報(bào)告應(yīng)用程式基礎(chǔ)結(jié)構(gòu)元件的健康情況。

應(yīng)用程式會(huì)將健康狀態(tài)檢查公開(kāi)為 HTTP 端點(diǎn)。 您可以針對(duì)各種即時(shí)監(jiān)控案例來(lái)設(shè)定健康情況檢查端點(diǎn):

容器協(xié)調(diào)器和負(fù)載平衡器可以使用健康狀態(tài)探查,來(lái)檢查應(yīng)用程式的狀態(tài)。 例如,容器協(xié)調(diào)器可能會(huì)暫停輪流部署或重新啟動(dòng)容器,來(lái)回應(yīng)失敗的健康狀態(tài)檢查。 負(fù)載平衡器可能會(huì)將流量從失敗的執(zhí)行個(gè)體路由傳送至狀況良好的執(zhí)行個(gè)體,來(lái)回應(yīng)狀況不良的應(yīng)用程式。 您可以監(jiān)控所使用記憶體、磁碟及其他實(shí)體伺服器資源的健康狀態(tài)。 健康狀態(tài)檢查可以測(cè)試應(yīng)用程式的相依性 (例如資料庫(kù)和外部服務(wù)端點(diǎn)),確認(rèn)其是否可用且正常運(yùn)作。

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

範(fàn)例應(yīng)用程式包括本文中所述的案例範(fàn)例。 若要在指定的案例中執(zhí)行範(fàn)例應(yīng)用程式,請(qǐng)?jiān)诿顨又惺褂脕?lái)自專案資料夾的 dotnet run 命令。 如需如何使用範(fàn)例應(yīng)用程式的詳細(xì)資料,請(qǐng)參閱範(fàn)例應(yīng)用程式的 README.md 檔案和本文中的案例描述。

必要條件

健康情況檢查通常會(huì)與外部監(jiān)控服務(wù)或容器協(xié)調(diào)器搭配使用,來(lái)檢查應(yīng)用程式的狀態(tài)。 將健康狀態(tài)檢查新增至應(yīng)用程式之前,請(qǐng)決定要使用的監(jiān)控系統(tǒng)。 監(jiān)控系統(tǒng)會(huì)指定要建立哪些健康狀態(tài)檢查類型,以及如何設(shè)定其端點(diǎn)。

ASP.NET Core 應(yīng)用程式會(huì)隱含參考 Microsoft.AspNetCore.Diagnostics.HealthChecks 套件。 若要使用 Entity Framework Core 來(lái)執(zhí)行健康情況檢查,請(qǐng)新增 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 套件的套件參考。

範(fàn)例應(yīng)用程式提供啟動(dòng)程式碼,來(lái)示範(fàn)數(shù)個(gè)案例的健康狀態(tài)檢查。 資料庫(kù)探查案例使用 AspNetCore.Diagnostics.HealthChecks 來(lái)檢查資料庫(kù)連線的健康情況。 DbContext 探查案例使用 EF CoreDbContext 來(lái)檢查資料庫(kù)。 為了探索資料庫(kù)案例,範(fàn)例應(yīng)用程式會(huì):

建立資料庫(kù),並在 appsettings.json 檔案中提供其連接字串。 在其專案檔中具有下列套件參考: AspNetCore.HealthChecks.SqlServer Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore

另一個(gè)健康狀態(tài)檢查案例示範(fàn)如何將健康狀態(tài)檢查篩選至管理連接埠。 範(fàn)例應(yīng)用程式需要您建立 Properties/launchSettings.json 檔案,而此檔案包括管理 URL 和管理連接埠。 如需詳細(xì)資訊,請(qǐng)參閱依連接埠篩選一節(jié)。

基本健康狀態(tài)探查

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

基本設(shè)定會(huì)登錄健康情況檢查服務(wù),並呼叫健康情況檢查中介軟體以在具有健康情況回應(yīng)的 URL 端點(diǎn)做出回應(yīng)。 預(yù)設(shè)並未登錄特定健康狀態(tài)檢查來(lái)測(cè)試任何特定相依性或子系統(tǒng)。 如果應(yīng)用程式可以在健康情況端點(diǎn) URL 做出回應(yīng),則視為狀況良好。 預(yù)設(shè)回應(yīng)寫(xiě)入器會(huì)將狀態(tài) (HealthStatus) 以純文字回應(yīng)形式回寫(xiě)至用戶端,指出 HealthStatus.Healthy、HealthStatus.Degraded 或 HealthStatus.Unhealthy 狀態(tài)。

在 Startup.ConfigureServices 中,使用 AddHealthChecks 登錄健康狀態(tài)檢查服務(wù)。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點(diǎn)。

在範(fàn)例應(yīng)用程式中,是在 /health (BasicStartup.cs) 建立健康情況檢查端點(diǎn):

public class BasicStartup { public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); } }

若要使用範(fàn)例應(yīng)用程式執(zhí)行基本組態(tài)案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario basic

Docker 範(fàn)例

Docker 提供內(nèi)建 HEALTHCHECK 指示詞,可用來(lái)檢查使用基本健康狀態(tài)檢查組態(tài)的應(yīng)用程式狀態(tài):

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

建立健康狀態(tài)檢查

健康狀態(tài)檢查是藉由實(shí)作 IHealthCheck 介面來(lái)建立。 CheckHealthAsync 方法會(huì)傳回指出狀態(tài)為 Healthy、Degraded 或 Unhealthy 的 HealthCheckResult。 結(jié)果會(huì)寫(xiě)成具有可設(shè)定狀態(tài)碼的純文字回應(yīng) (健康狀態(tài)檢查選項(xiàng)一節(jié)中將說(shuō)明如何進(jìn)行組態(tài))。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

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

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

登錄健康狀態(tài)檢查服務(wù)

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

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

下列範(fàn)例中所顯示的 AddCheck 多載會(huì)設(shè)定在健康狀態(tài)檢查報(bào)告失敗時(shí)所要報(bào)告的失敗狀態(tài) (HealthStatus)。 如果將失敗狀態(tài)設(shè)定為 null (預(yù)設(shè)),則會(huì)報(bào)告 HealthStatus.Unhealthy。 此多載對(duì)程式庫(kù)作者很有用。若健康狀態(tài)檢查實(shí)作採(cǎi)用此設(shè)定,則當(dāng)健康狀態(tài)檢查失敗時(shí),應(yīng)用程式就會(huì)強(qiáng)制程式庫(kù)指出失敗狀態(tài)。

您可以使用「標(biāo)籤」來(lái)篩選健康狀態(tài)檢查 (篩選健康狀態(tài)檢查一節(jié)中將進(jìn)一步說(shuō)明)。

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

AddCheck 也可以執(zhí)行匿名函式。 在下列範(fàn)例中,健康狀態(tài)檢查名稱指定為 Example,且檢查一律會(huì)傳回狀況良好狀態(tài):

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

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

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) { ... } }

使用傳遞至實(shí)作的整數(shù)和字串來(lái)呼叫 AddTypeActivatedCheck,以登錄 TestHealthCheckWithArgs:

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

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

在 Startup.Configure 中,使用端點(diǎn) URL 或相對(duì)路徑以在端點(diǎn)建立器上呼叫 MapHealthChecks:

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

需要主機(jī)

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

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

如需詳細(xì)資訊,請(qǐng)參閱依連接埠篩選一節(jié)。

需要授權(quán)

呼叫 RequireAuthorization,以在健康情況檢查要求端點(diǎn)上執(zhí)行授權(quán)中介軟體。 RequireAuthorization 多載接受一或多個(gè)授權(quán)原則。 如果未提供原則,則會(huì)使用預(yù)設(shè)授權(quán)原則。

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

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

雖然從瀏覽器手動(dòng)執(zhí)行健康情況檢查不是常見(jiàn)使用案例,但是您可以在健康情況檢查端點(diǎn)上呼叫 RequireCors,以啟用 CORS 中介軟體。 RequireCors 多載接受 CORS 原則建立器委派 (CorsPolicyBuilder) 或原則名稱。 如果未提供原則,則會(huì)使用預(yù)設(shè) CORS 原則。 如需詳細(xì)資訊,請(qǐng)參閱在 ASP.NET Core 中啟用跨原始來(lái)源要求 (CORS)。

健康狀態(tài)檢查選項(xiàng)

HealthCheckOptions 讓您有機(jī)會(huì)自訂健康狀態(tài)檢查行為:

篩選健康狀態(tài)檢查 自訂 HTTP 狀態(tài)碼 隱藏快取標(biāo)頭 自訂輸出

篩選健康狀態(tài)檢查

根據(jù)預(yù)設(shè),健康情況檢查中介軟體會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行健康狀態(tài)檢查子集,請(qǐng)對(duì) Predicate 選項(xiàng)提供傳回布林值的函式。 在下列範(fàn)例中,會(huì)依函式條件陳述式中的標(biāo)籤 (bar_tag) 篩選出 Bar 健康狀態(tài)檢查。只有在健康狀態(tài)檢查的 Tags 屬性符合 foo_tag 或 baz_tag 時(shí),才傳回 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 會(huì)篩選出「橫條圖」健康情況檢查。 只有 Foo 和 Baz 才能執(zhí)行:

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

自訂 HTTP 狀態(tài)碼

您可以使用 ResultStatusCodes 來(lái)自訂健康狀態(tài)與 HTTP 狀態(tài)碼的對(duì)應(yīng)。 下列 StatusCodes 指派是中介軟體所使用的預(yù)設(shè)值。 請(qǐng)變更狀態(tài)碼值以符合您的需求。

在 Startup.Configure 中:

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

隱藏快取標(biāo)頭

AllowCachingResponses 會(huì)控制健康情況檢查中介軟體是否將 HTTP 標(biāo)頭新增至探查回應(yīng),以防止回應(yīng)快取。 如果值為 false (預(yù)設(shè)),則中介軟體會(huì)設(shè)定或覆寫(xiě) Cache-Control、Expires 和 Pragma 標(biāo)頭,以防止回應(yīng)快取。 如果值為 true,則中介軟體不會(huì)修改回應(yīng)的快取標(biāo)頭。

在 Startup.Configure 中:

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

自訂輸出

在 Startup.Configure 中,將 HealthCheckOptions.ResponseWriter 選項(xiàng)設(shè)定為撰寫(xiě)回應(yīng)的委派:

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

預(yù)設(shè)委派會(huì)使用字串值 HealthReport.Status 寫(xiě)入基本純文字回應(yīng)。 下列自訂委派會(huì)輸出自訂 JSON 回應(yīng)。

範(fàn)例應(yīng)用程式中的第一個(gè)範(fàn)例示範(fàn)如何使用 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); } }

第二個(gè)範(fàn)例示範(fàn)如何使用 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)); }

在範(fàn)例應(yīng)用程式中,註解化 CustomWriterStartup.cs 中的 SYSTEM_TEXT_JSON 前置處理器指示詞,以啟用 WriteResponse 的 Newtonsoft.Json 版本。

健康情況檢查 API 未提供複雜 JSON 傳回格式的內(nèi)建支援,因?yàn)榇烁袷绞悄x擇的監(jiān)控系統(tǒng)所特有。 視需要,自訂上述範(fàn)例中的回應(yīng)。 如需使用 System.Text.Json進(jìn)行 JSON 序列化的詳細(xì)資訊,請(qǐng)參閱 如何在 .NET 中序列化和還原序列化 JSON。

資料庫(kù)探查

健康狀態(tài)檢查可指定資料庫(kù)查詢以布林測(cè)試方式來(lái)執(zhí)行,藉此指出資料庫(kù)是否正?;貞?yīng)。

範(fàn)例應(yīng)用程式使用 AspNetCore.Diagnostics.HealthChecks (一種適用於 ASP.NET Core 應(yīng)用程式的健康情況檢查程式庫(kù)),以在 SQL Server 資料庫(kù)上執(zhí)行健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會(huì)對(duì)資料庫(kù)執(zhí)行 SELECT 1 查詢,以確認(rèn)資料庫(kù)連線狀況良好。

警告

使用查詢檢查資料庫(kù)連線時(shí),請(qǐng)選擇快速傳回的查詢。 查詢方法具有多載資料庫(kù)而降低其效能的風(fēng)險(xiǎn)。 在大部分情況下,不需要執(zhí)行測(cè)試查詢。 只要成功建立資料庫(kù)連線就已足夠。 如果您發(fā)現(xiàn)有必要執(zhí)行查詢,請(qǐng)選擇簡(jiǎn)單的 SELECT 查詢,例如 SELECT 1。

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

在範(fàn)例應(yīng)用程式的 appsettings.json 檔案中,提供有效的資料庫(kù)連接字串。 應(yīng)用程式使用名為 HealthCheckSample 的 SQL Server 資料庫(kù):

{ "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 登錄健康狀態(tài)檢查服務(wù)。 範(fàn)例應(yīng)用程式會(huì)使用資料庫(kù)連接字串 (DbHealthStartup.cs) 來(lái)呼叫 AddSqlServer 方法:

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

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks:

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

若要使用範(fàn)例應(yīng)用程式執(zhí)行資料庫(kù)探查案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario db

Entity Framework Core DbContext 探查

DbContext 檢查會(huì)確認(rèn)應(yīng)用程式是否可以與針對(duì) EF CoreDbContext 所設(shè)定的資料庫(kù)通訊。 應(yīng)用程式支援 DbContext 檢查:

使用 Entity Framework (EF) Core。 包括 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 的套件參考。

AddDbContextCheck<TContext> 會(huì)登錄 DbContext 的健康狀態(tài)檢查。 DbContext 會(huì)以 TContext 形式提供給方法。 多載可用來(lái)設(shè)定失敗狀態(tài)、標(biāo)籤和自訂測(cè)試查詢。

預(yù)設(shè)情況:

DbContextHealthCheck 會(huì)呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態(tài)時(shí)所要執(zhí)行的作業(yè)。 健康狀態(tài)檢查的名稱是 TContext 類型的名稱。

在範(fàn)例應(yīng)用程式中,會(huì)將 AppDbContext 提供給 AddDbContextCheck,並在 Startup.ConfigureServices 中登錄為服務(wù) (DbContextHealthStartup.cs):

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

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks:

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

若要使用範(fàn)例應(yīng)用程式來(lái)執(zhí)行 DbContext 探查案例,請(qǐng)確認(rèn) SQL Server 執(zhí)行個(gè)體中沒(méi)有連接字串所指定的資料庫(kù)。 如果資料庫(kù)存在,請(qǐng)予以刪除。

在命令殼層中執(zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario dbcontext

在應(yīng)用程式執(zhí)行之後,對(duì)瀏覽器中的 /health 端點(diǎn)提出要求來(lái)檢查健康狀態(tài)。 資料庫(kù)和 AppDbContext 不存在,因此應(yīng)用程式會(huì)提供下列回應(yīng):

Unhealthy

觸發(fā)範(fàn)例應(yīng)用程式以建立資料庫(kù)。 對(duì) /createdatabase 提出要求。 應(yīng)用程式會(huì)回應(yīng):

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

對(duì) /health 端點(diǎn)提出要求。 資料庫(kù)和內(nèi)容存在,因此應(yīng)用程式會(huì)回應(yīng):

Healthy

觸發(fā)範(fàn)例應(yīng)用程式以刪除資料庫(kù)。 對(duì) /deletedatabase 提出要求。 應(yīng)用程式會(huì)回應(yīng):

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

對(duì) /health 端點(diǎn)提出要求。 應(yīng)用程式會(huì)提供狀況不良回應(yīng):

Unhealthy

個(gè)別的整備度與活躍度探查

在某些裝載案例中,會(huì)使用一組健康情況檢查來(lái)區(qū)分兩個(gè)應(yīng)用程式狀態(tài):

「整備」指出應(yīng)用程式是否正在正常執(zhí)行,但尚未準(zhǔn)備好接收要求。 「活躍度」指出應(yīng)用程式是否已當(dāng)機(jī),而且必須重新予以啟動(dòng)。

請(qǐng)考慮下列範(fàn)例:應(yīng)用程式在準(zhǔn)備好處理要求之前必須下載大型設(shè)定檔。 如果初始下載失敗,則我們不想要重新啟動(dòng)應(yīng)用程式,因?yàn)閼?yīng)用程式可以重試下載檔案數(shù)次。 我們使用「活躍度探查」來(lái)描述處理序的活躍度,而不會(huì)執(zhí)行其他檢查。 我們也想要防止在設(shè)定檔下載成功之前將要求傳送至應(yīng)用程式。 除非下載成功,而且應(yīng)用程式準(zhǔn)備好接收要求,否則我們會(huì)使用「整備度探查」來(lái)指出「尚未就緒」?fàn)顟B(tài)。

範(fàn)例應(yīng)用程式包含健康狀態(tài)檢查,會(huì)在託管服務(wù)中長(zhǎng)時(shí)間執(zhí)行的啟動(dòng)工作完成時(shí)回報(bào)。 StartupHostedServiceHealthCheck 會(huì)公開(kāi) StartupTaskCompleted 屬性,而裝載的服務(wù)可以在其長(zhǎng)時(shí)間執(zhí)行的工作完成時(shí),將此屬性設(shè)定為 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.")); } }

裝載的服務(wù) (Services/StartupHostedService) 會(huì)啟動(dòng)長(zhǎng)時(shí)間執(zhí)行的背景工作。 工作完成時(shí),StartupHostedServiceHealthCheck.StartupTaskCompleted 會(huì)設(shè)定為 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() { } }

健康狀態(tài)檢查是 Startup.ConfigureServices 中使用 AddCheck 隨託管服務(wù)一起登錄。 因?yàn)樗b載服務(wù)必須在健康情況檢查上設(shè)定此屬性,所以也會(huì)在服務(wù)容器中登錄健康情況檢查 (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>();

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 在範(fàn)例應(yīng)用程式中,是在下列位置建立健康情況檢查端點(diǎn):

/health/ready 用於整備檢查。 整備度檢查使用 ready 標(biāo)籤來(lái)篩選健康狀態(tài)檢查。 /health/live 用於活躍度檢查。 活躍度檢查是在 HealthCheckOptions.Predicate 中傳回 false 來(lái)篩選出 StartupHostedServiceHealthCheck (如需詳細(xì)資訊,請(qǐng)參閱篩選健康情況檢查)

在下列範(fàn)例程式碼中:

整備檢查會(huì)使用具有「就緒」標(biāo)記的所有已登錄檢查。 Predicate 會(huì)排除所有檢查,並傳回 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 }); }

若要使用範(fàn)例應(yīng)用程式執(zhí)行整備度/活躍度組態(tài)案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario liveness

在瀏覽器中,瀏覽 /health/ready 數(shù)次,直到經(jīng)過(guò) 15 秒。 健康狀態(tài)檢查報(bào)告前 15 秒為 Unhealthy。 15 秒之後,端點(diǎn)會(huì)報(bào)告 Healthy,以反映託管服務(wù)長(zhǎng)時(shí)間執(zhí)行的工作已完成。

此範(fàn)例也會(huì)建立一個(gè)以兩秒延遲執(zhí)行第一次整備檢查的「健康情況檢查發(fā)行者」(IHealthCheckPublisher 實(shí)作)。 如需詳細(xì)資訊,請(qǐng)參閱健康狀態(tài)檢查發(fā)行者一節(jié)。

Kubernetes 範(fàn)例

使用個(gè)別的整備度與活躍度檢查在 Kubernetes 之類的環(huán)境中很有用。 在 Kubernetes 中,應(yīng)用程式可能需要先執(zhí)行耗時(shí)的啟動(dòng)工作,才能接受要求 (例如基礎(chǔ)資料庫(kù)可用性測(cè)試)。 使用個(gè)別的檢查可讓協(xié)調(diào)器區(qū)分應(yīng)用程式是否為正常運(yùn)作但尚未準(zhǔn)備好,或應(yīng)用程式是否無(wú)法啟動(dòng)。 如需 Kubernetes 中整備度與活躍度探查的詳細(xì)資訊,請(qǐng)參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設(shè)定活躍度與整備度探查)。

下列範(fàn)例示範(fàn) Kubernetes 整備度探查組態(tài):

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

透過(guò)自訂回應(yīng)寫(xiě)入器的計(jì)量型探查

範(fàn)例應(yīng)用程式示範(fàn)透過(guò)自訂回應(yīng)寫(xiě)入器的記憶體健康狀態(tài)檢查。

如果應(yīng)用程式使用超過(guò)指定的記憶體閾值 (在範(fàn)例應(yīng)用程式中為 1 GB),MemoryHealthCheck 會(huì)報(bào)告降級(jí)的狀態(tài)。 HealthCheckResult 包括應(yīng)用程式的記憶體回收行程 (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 登錄健康狀態(tài)檢查服務(wù)。 MemoryHealthCheck 會(huì)登錄為服務(wù),而不是將健康狀態(tài)檢查傳遞至 AddCheck 以啟用檢查。 所有 IHealthCheck 登錄的服務(wù)都可供健康狀態(tài)檢查服務(wù)和中介軟體使用。 建議將健康狀態(tài)檢查服務(wù)登錄為單一服務(wù)。

在範(fàn)例應(yīng)用程式的 CustomWriterStartup.cs 中:

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

健康情況檢查端點(diǎn)的建立方式是在 Startup.Configure 中呼叫 MapHealthChecks。 當(dāng)健康狀態(tài)檢查執(zhí)行時(shí),會(huì)將 WriteResponse 委派提供給 ResponseWriter 屬性以輸出自訂 JSON 回應(yīng):

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

WriteResponse 委派會(huì)將 CompositeHealthCheckResult 格式化為 JSON 物件,並產(chǎn)生健康情況檢查回應(yīng)的 JSON 輸出。 如需詳細(xì)資訊,請(qǐng)參閱自訂輸出小節(jié)。

若要使用範(fàn)例應(yīng)用程式透過(guò)自訂回應(yīng)寫(xiě)入器輸出執(zhí)行計(jì)量型探查,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario writer

依連接埠篩選

使用 URL 模式以在 MapHealthChecks 上呼叫 RequireHost,而此模式指定連接埠來(lái)限制針對(duì)所指定連接埠的健康情況檢查要求。 此方式通常用於容器環(huán)境,以公開(kāi)監(jiān)控服務(wù)的連接埠。

範(fàn)例應(yīng)用程式使用環(huán)境變數(shù)組態(tài)提供者來(lái)設(shè)定連接埠。 連接埠是在 launchSettings.json 檔案中設(shè)定,並透過(guò)環(huán)境變數(shù)傳遞至設(shè)定提供者。 您也必須將伺服器設(shè)定為在管理連接埠上接聽(tīng)要求。

若要使用範(fàn)例應(yīng)用程式來(lái)示範(fàn)管理連接埠設(shè)定,請(qǐng)?jiān)?Properties 資料夾中建立 launchSettings.json 檔案。

範(fàn)例應(yīng)用程式中的下列 Properties/launchSettings.json 檔案未包括在範(fàn)例應(yīng)用程式的專案檔中,而且必須手動(dòng)予以建立:

{ "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 登錄健康狀態(tài)檢查服務(wù)。 在 Startup.Configure 中呼叫 MapHealthChecks,以建立健康情況檢查端點(diǎn)。

在範(fàn)例應(yīng)用程式中,對(duì) Startup.Configure 中端點(diǎn)的 RequireHost 呼叫指定設(shè)定管理連接埠:

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

在範(fàn)例應(yīng)用程式的 Startup.Configure 中,建立端點(diǎn)。 在下列範(fàn)例程式碼中:

整備檢查會(huì)使用具有「就緒」標(biāo)記的所有已登錄檢查。 Predicate 會(huì)排除所有檢查,並傳回 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 }); }

注意

您可以在程式碼中明確設(shè)定管理連接埠,以避免在範(fàn)例應(yīng)用程式中建立 launchSettings.json 檔案。 在 HostBuilder 建立所在的 Program.cs 中,新增 ListenAnyIP 呼叫,並提供應(yīng)用程式的管理連接埠端點(diǎn)。 在 ManagementPortStartup.cs 的 Configure 中,使用 RequireHost 來(lái)指定管理連接埠:

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

若要使用範(fàn)例應(yīng)用程式執(zhí)行管理連接埠組態(tài)案例,請(qǐng)?jiān)诿顨又袌?zhí)行來(lái)自專案資料夾的下列命令:

dotnet run --scenario port

發(fā)佈健康狀態(tài)檢查程式庫(kù)

若要發(fā)佈健康狀態(tài)檢查作為程式庫(kù):

寫(xiě)入健康狀態(tài)檢查,將 IHealthCheck 介面當(dāng)做獨(dú)立類別來(lái)實(shí)作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項(xiàng)來(lái)存取組態(tài)資料。

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

data1 和 data2 用於此方法,以執(zhí)行探查的健康情況檢查邏輯。 已處理 AccessViolationException。

發(fā)生 AccessViolationException 時(shí),會(huì)使用 HealthCheckResult 來(lái)傳回 FailureStatus,以允許使用者設(shè)定健康情況檢查失敗狀態(tài)。

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

使用取用應(yīng)用程式在其 Startup.Configure 方法中呼叫的參數(shù),來(lái)寫(xiě)入延伸模組。 在下列範(fàn)例中,假設(shè)健康狀態(tài)檢查方法簽章如下:

ExampleHealthCheck(string, string, int )

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

健康狀態(tài)檢查名稱 (name)。 如果為 null,則會(huì)使用 example_health_check。 健康狀態(tài)檢查的字串資料點(diǎn) (data1)。 健康狀態(tài)檢查的整數(shù)資料點(diǎn) (data2)。 如果為 null,則會(huì)使用 1。 失敗狀態(tài) (HealthStatus)。 預(yù)設(shè)值為 null。 如果為 null,則會(huì)報(bào)告失敗狀態(tài)為 HealthStatus.Unhealthy。 標(biāo)籤 (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)); } }

健康狀態(tài)檢查發(fā)行者

當(dāng) IHealthCheckPublisher 新增至服務(wù)容器時(shí),健康狀態(tài)檢查系統(tǒng)會(huì)定期執(zhí)行健康狀態(tài)檢查,並呼叫 PublishAsync 傳回結(jié)果。 這對(duì)推送型健康狀態(tài)監(jiān)控系統(tǒng)案例很有用,其預(yù)期每個(gè)處理序會(huì)定期呼叫監(jiān)控系統(tǒng)來(lái)判斷健康狀態(tài)。

IHealthCheckPublisher 介面有單一方法:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions 可讓您設(shè)定:

Delay:初始延遲會(huì)在應(yīng)用程式啟動(dòng)之後且執(zhí)行 IHealthCheckPublisher 執(zhí)行個(gè)體之前套用。 在啟動(dòng)後就會(huì)套用延遲,但不會(huì)套用至後續(xù)的反覆項(xiàng)目。 預(yù)設(shè)值是五秒鐘。 Period:IHealthCheckPublisher 執(zhí)行的期間。 預(yù)設(shè)值為 30 秒。 Predicate:如果 Predicate 為 null (預(yù)設(shè)),則健康情況檢查發(fā)行者服務(wù)會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行一部分的健康狀態(tài)檢查,請(qǐng)?zhí)峁┛珊Y選該組檢查的函式。 每個(gè)期間都會(huì)評(píng)估該述詞。 Timeout:執(zhí)行所有 IHealthCheckPublisher 執(zhí)行個(gè)體之健康情況檢查的逾時(shí)。 若要在沒(méi)有逾時(shí)的情況下執(zhí)行,請(qǐng)使用 InfiniteTimeSpan。 預(yù)設(shè)值為 30 秒。

在範(fàn)例應(yīng)用程式中,ReadinessPublisher 是一個(gè) IHealthCheckPublisher 實(shí)作。 在下列記錄層級(jí),會(huì)記錄每個(gè)檢查的健康情況檢查狀態(tài):

如果健康情況檢查狀態(tài)為 Healthy,則為資訊 (LogInformation)。 如果狀態(tài)為 Degraded 或 Unhealthy,則為錯(cuò)誤 (LogError)。

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; } }

在範(fàn)例應(yīng)用程式的 LivenessProbeStartup 範(fàn)例中,StartupHostedService 整備檢查具有 2 秒的啟動(dòng)延遲,且每 30 秒會(huì)執(zhí)行一次檢查。 為了啟用 IHealthCheckPublisher 實(shí)作,此範(fàn)例會(huì)在相依性插入 (DI) 容器中將 ReadinessPublisher 註冊(cè)為單一服務(wù):

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>();

利用 MapWhen 限制健康情況檢查

使用 MapWhen 來(lái)有條件地將健康情況檢查端點(diǎn)的要求管線分支。

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

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

如需詳細(xì)資訊,請(qǐng)參閱 ASP.NET Core 中介軟體。

ASP.NET Core 提供健康情況檢查中介軟體和程式庫(kù),用來(lái)報(bào)告應(yīng)用程式基礎(chǔ)結(jié)構(gòu)元件的健康情況。

應(yīng)用程式會(huì)將健康狀態(tài)檢查公開(kāi)為 HTTP 端點(diǎn)。 您可以針對(duì)各種即時(shí)監(jiān)控案例來(lái)設(shè)定健康情況檢查端點(diǎn):

容器協(xié)調(diào)器和負(fù)載平衡器可以使用健康狀態(tài)探查,來(lái)檢查應(yīng)用程式的狀態(tài)。 例如,容器協(xié)調(diào)器可能會(huì)暫停輪流部署或重新啟動(dòng)容器,來(lái)回應(yīng)失敗的健康狀態(tài)檢查。 負(fù)載平衡器可能會(huì)將流量從失敗的執(zhí)行個(gè)體路由傳送至狀況良好的執(zhí)行個(gè)體,來(lái)回應(yīng)狀況不良的應(yīng)用程式。 您可以監(jiān)控所使用記憶體、磁碟及其他實(shí)體伺服器資源的健康狀態(tài)。 健康狀態(tài)檢查可以測(cè)試應(yīng)用程式的相依性 (例如資料庫(kù)和外部服務(wù)端點(diǎn)),確認(rèn)其是否可用且正常運(yùn)作。

健康情況檢查通常會(huì)與外部監(jiān)控服務(wù)或容器協(xié)調(diào)器搭配使用,來(lái)檢查應(yīng)用程式的狀態(tài)。 將健康狀態(tài)檢查新增至應(yīng)用程式之前,請(qǐng)決定要使用的監(jiān)控系統(tǒng)。 監(jiān)控系統(tǒng)會(huì)指定要建立哪些健康狀態(tài)檢查類型,以及如何設(shè)定其端點(diǎn)。

基本健康狀態(tài)探查

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

基本設(shè)定會(huì)登錄健康情況檢查服務(wù),並呼叫健康情況檢查中介軟體以在具有健康情況回應(yīng)的 URL 端點(diǎn)做出回應(yīng)。 預(yù)設(shè)並未登錄特定健康狀態(tài)檢查來(lái)測(cè)試任何特定相依性或子系統(tǒng)。 如果應(yīng)用程式可以在健康情況端點(diǎn) URL 做出回應(yīng),則視為狀況良好。 預(yù)設(shè)回應(yīng)寫(xiě)入器會(huì)將 HealthStatus 以純文字回應(yīng)形式寫(xiě)入至用戶端。 HealthStatus 是 HealthStatus.Healthy、HealthStatus.Degraded 或 HealthStatus.Unhealthy。

在 Program.cs 中,使用 AddHealthChecks 登錄健康狀態(tài)檢查服務(wù)。 呼叫 MapHealthChecks 來(lái)建立健康情況檢查端點(diǎn)。

下列範(fàn)例會(huì)在 /healthz 建立健康情況檢查端點(diǎn):

var builder = WebApplication.CreateBuilder(args); builder.Services.AddHealthChecks(); var app = builder.Build(); app.MapHealthChecks("/healthz"); app.Run();

Docker HEALTHCHECK

Docker 提供內(nèi)建 HEALTHCHECK 指示詞,可用來(lái)檢查使用基本健康狀態(tài)檢查組態(tài)的應(yīng)用程式狀態(tài):

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

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

建立健康狀態(tài)檢查

健康狀態(tài)檢查是藉由實(shí)作 IHealthCheck 介面來(lái)建立。 CheckHealthAsync 方法會(huì)傳回指出狀態(tài)為 Healthy、Degraded 或 Unhealthy 的 HealthCheckResult。 結(jié)果會(huì)寫(xiě)成具有可設(shè)定狀態(tài)碼的純文字回應(yīng)。 健康情況檢查選項(xiàng)小節(jié)中會(huì)描述設(shè)定。 HealthCheckResult 也可以傳回選擇性索引鍵/值組。

下列範(fàn)例示範(fàn)健康情況檢查的配置:

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 方法中。 上述範(fàn)例會(huì)將虛擬變數(shù) isHealthy 設(shè)定為 true。 如果 isHealthy 的值設(shè)定為 false,則會(huì)傳回 HealthCheckRegistration.FailureStatus 狀態(tài)。

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

登錄健康狀態(tài)檢查服務(wù)

若要登錄健康情況檢查服務(wù),請(qǐng)?jiān)?Program.cs 中呼叫 AddCheck:

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

下列範(fàn)例中所顯示的 AddCheck 多載會(huì)設(shè)定在健康狀態(tài)檢查報(bào)告失敗時(shí)所要報(bào)告的失敗狀態(tài) (HealthStatus)。 如果將失敗狀態(tài)設(shè)定為 null (預(yù)設(shè)),則會(huì)報(bào)告 HealthStatus.Unhealthy。 此多載對(duì)程式庫(kù)作者很有用。若健康狀態(tài)檢查實(shí)作採(cǎi)用此設(shè)定,則當(dāng)健康狀態(tài)檢查失敗時(shí),應(yīng)用程式就會(huì)強(qiáng)制程式庫(kù)指出失敗狀態(tài)。

「標(biāo)記」可以用來(lái)篩選健康情況檢查。 標(biāo)記會(huì)在篩選健康情況檢查小節(jié)中予以描述。

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

AddCheck 也可以執(zhí)行匿名函式。 在下列範(fàn)例中,健康情況檢查一律會(huì)傳回狀況良好結(jié)果:

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

呼叫 AddTypeActivatedCheck,以將引數(shù)傳遞至健康情況檢查實(shí)作。 在下列範(fàn)例中,啟用類型的健康情況檢查會(huì)在其建構(gòu)函式中接受整數(shù)和字串:

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

若要登錄上述健康情況檢查,請(qǐng)使用傳遞為引數(shù)的整數(shù)和字串來(lái)呼叫 AddTypeActivatedCheck:

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

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

在 Program.cs 中,使用端點(diǎn) URL 或相對(duì)路徑以在端點(diǎn)建立器上呼叫 MapHealthChecks:

app.MapHealthChecks("/healthz");

需要主機(jī)

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

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

若要限制健康情況檢查端點(diǎn)只在特定連接埠上回應(yīng),請(qǐng)?jiān)?RequireHost 呼叫中指定連接埠。 此方式通常用於容器環(huán)境,以公開(kāi)監(jiān)控服務(wù)的連接埠:

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

若要防止未經(jīng)授權(quán)的用戶端詐騙連接埠,請(qǐng)呼叫 RequireAuthorization:

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

如需詳細(xì)資訊,請(qǐng)參閱具有 RequireHost 之路由中的主機(jī)比對(duì)。

需要授權(quán)

呼叫 RequireAuthorization,以在健康情況檢查要求端點(diǎn)上執(zhí)行授權(quán)中介軟體。 RequireAuthorization 多載接受一或多個(gè)授權(quán)原則。 如果未提供原則,則會(huì)使用預(yù)設(shè)授權(quán)原則:

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

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

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

健康狀態(tài)檢查選項(xiàng)

HealthCheckOptions 讓您有機(jī)會(huì)自訂健康狀態(tài)檢查行為:

篩選健康狀態(tài)檢查 自訂 HTTP 狀態(tài)碼 隱藏快取標(biāo)頭 自訂輸出

篩選健康狀態(tài)檢查

根據(jù)預(yù)設(shè),健康情況檢查中介軟體會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行健康狀態(tài)檢查子集,請(qǐng)對(duì) Predicate 選項(xiàng)提供傳回布林值的函式。

下列範(fàn)例會(huì)篩選健康情況檢查,以只執(zhí)行已標(biāo)記 sample 的檢查:

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

自訂 HTTP 狀態(tài)碼

您可以使用 ResultStatusCodes 來(lái)自訂健康狀態(tài)與 HTTP 狀態(tài)碼的對(duì)應(yīng)。 下列 StatusCodes 指派是中介軟體所使用的預(yù)設(shè)值。 變更狀態(tài)碼值,以符合您的需求:

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

隱藏快取標(biāo)頭

AllowCachingResponses 會(huì)控制健康情況檢查中介軟體是否將 HTTP 標(biāo)頭新增至探查回應(yīng),以防止回應(yīng)快取。 如果值為 false (預(yù)設(shè)),則中介軟體會(huì)設(shè)定或覆寫(xiě) Cache-Control、Expires 和 Pragma 標(biāo)頭,以防止回應(yīng)快取。 如果值為 true,則中介軟體不會(huì)修改回應(yīng)的快取標(biāo)頭:

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

自訂輸出

若要自訂健康情況檢查報(bào)告的輸出,請(qǐng)將 HealthCheckOptions.ResponseWriter 屬性設(shè)定為可寫(xiě)入回應(yīng)的委派:

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

預(yù)設(shè)委派會(huì)使用字串值 HealthReport.Status 寫(xiě)入基本純文字回應(yīng)。 下列自訂委派會(huì)使用 System.Text.Json來(lái)輸出自訂 JSON 回應(yīng):

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 傳回格式的內(nèi)建支援,因?yàn)榇烁袷绞悄x擇的監(jiān)控系統(tǒng)所特有。 視需要,自訂上述範(fàn)例中的回應(yīng)。 如需使用 System.Text.Json進(jìn)行 JSON 序列化的詳細(xì)資訊,請(qǐng)參閱 如何在 .NET 中序列化和還原序列化 JSON。

資料庫(kù)探查

健康狀態(tài)檢查可指定資料庫(kù)查詢以布林測(cè)試方式來(lái)執(zhí)行,藉此指出資料庫(kù)是否正?;貞?yīng)。

AspNetCore.Diagnostics.HealthChecks,一種適用於 ASP.NET Core 應(yīng)用程式的健康情況檢查程式庫(kù),包括針對(duì) SQL Server 資料庫(kù)所執(zhí)行的健康情況檢查。 AspNetCore.Diagnostics.HealthChecks 會(huì)對(duì)資料庫(kù)執(zhí)行 SELECT 1 查詢,以確認(rèn)資料庫(kù)連線狀況良好。

警告

使用查詢檢查資料庫(kù)連線時(shí),請(qǐng)選擇快速傳回的查詢。 查詢方法具有多載資料庫(kù)而降低其效能的風(fēng)險(xiǎn)。 在大部分情況下,不需要執(zhí)行測(cè)試查詢。 只要成功建立資料庫(kù)連線就已足夠。 如果您發(fā)現(xiàn)有必要執(zhí)行查詢,請(qǐng)選擇簡(jiǎn)單的 SELECT 查詢,例如 SELECT 1。

若要使用此 SQL Server 健康情況檢查,請(qǐng)包括 AspNetCore.HealthChecks.SqlServer NuGet 套件的套件參考。 下列範(fàn)例會(huì)登錄 SQL Server 健康情況檢查:

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

Entity Framework Core DbContext 探查

DbContext 檢查會(huì)確認(rèn)應(yīng)用程式是否可以與針對(duì) EF CoreDbContext 所設(shè)定的資料庫(kù)通訊。 應(yīng)用程式支援 DbContext 檢查:

使用 Entity Framework (EF) Core。 包括 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore NuGet 套件的套件參考。

AddDbContextCheck 會(huì)登錄 DbContext 的健康狀態(tài)檢查。 DbContext 會(huì)以 TContext 形式提供給方法。 多載可用來(lái)設(shè)定失敗狀態(tài)、標(biāo)籤和自訂測(cè)試查詢。

預(yù)設(shè)情況:

DbContextHealthCheck 會(huì)呼叫 EF Core 的 CanConnectAsync 方法。 您可以自訂使用 AddDbContextCheck 方法多載檢查健康狀態(tài)時(shí)所要執(zhí)行的作業(yè)。 健康狀態(tài)檢查的名稱是 TContext 類型的名稱。

下列範(fàn)例會(huì)登錄 DbContext 和相關(guān)聯(lián)的 DbContextHealthCheck:

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

個(gè)別的整備度與活躍度探查

在某些裝載案例中,會(huì)使用一組健康情況檢查來(lái)區(qū)分兩個(gè)應(yīng)用程式狀態(tài):

「整備」指出應(yīng)用程式是否正在正常執(zhí)行,但尚未準(zhǔn)備好接收要求。 「活躍度」指出應(yīng)用程式是否已當(dāng)機(jī),而且必須重新予以啟動(dòng)。

請(qǐng)考慮下列範(fàn)例:應(yīng)用程式在準(zhǔn)備好處理要求之前必須下載大型設(shè)定檔。 如果初始下載失敗,則我們不想要重新啟動(dòng)應(yīng)用程式,因?yàn)閼?yīng)用程式可以重試下載檔案數(shù)次。 我們使用「活躍度探查」來(lái)描述處理序的活躍度,而不會(huì)執(zhí)行其他檢查。 我們也想要防止在設(shè)定檔下載成功之前將要求傳送至應(yīng)用程式。 除非下載成功,而且應(yīng)用程式準(zhǔn)備好接收要求,否則我們會(huì)使用「整備度探查」來(lái)指出「尚未就緒」?fàn)顟B(tài)。

下列背景工作會(huì)模擬大約需要 15 秒的啟動(dòng)處理序。 完成後,工作會(huì)將 StartupHealthCheck.StartupCompleted 屬性設(shè)定為 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 會(huì)報(bào)告長(zhǎng)時(shí)間執(zhí)行的啟動(dòng)工作完成,並公開(kāi)背景服務(wù)所設(shè)定的 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.")); } }

健康狀態(tài)檢查是 Program.cs 中使用 AddCheck 隨託管服務(wù)一起登錄。 因?yàn)樗b載服務(wù)必須在健康情況檢查上設(shè)定此屬性,所以也會(huì)在服務(wù)容器中將健康情況檢查登錄為單一資料庫(kù):

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

若要建立兩個(gè)不同的健康情況檢查端點(diǎn),請(qǐng)呼叫 MapHealthChecks 兩次:

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

上述範(fàn)例會(huì)建立下列健康情況檢查端點(diǎn):

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

啟動(dòng)工作完成之前,/healthz/ready 端點(diǎn)會(huì)回報(bào) Unhealthy 狀態(tài)。 啟動(dòng)工作完成之後,此端點(diǎn)會(huì)回報(bào) Healthy 狀態(tài)。 /healthz/live 端點(diǎn)會(huì)排除所有檢查,並將所有呼叫的狀態(tài)都回報(bào)為 Healthy。

Kubernetes 範(fàn)例

使用個(gè)別的整備度與活躍度檢查在 Kubernetes 之類的環(huán)境中很有用。 在 Kubernetes 中,應(yīng)用程式可能需要先執(zhí)行耗時(shí)的啟動(dòng)工作,才能接受要求 (例如基礎(chǔ)資料庫(kù)可用性測(cè)試)。 使用個(gè)別的檢查可讓協(xié)調(diào)器區(qū)分應(yīng)用程式是否為正常運(yùn)作但尚未準(zhǔn)備好,或應(yīng)用程式是否無(wú)法啟動(dòng)。 如需 Kubernetes 中整備度與活躍度探查的詳細(xì)資訊,請(qǐng)參閱 Kubernetes 文件中的 Configure Liveness and Readiness Probes (設(shè)定活躍度與整備度探查)。

下列範(fàn)例示範(fàn) Kubernetes 整備度探查組態(tài):

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

發(fā)佈健康狀態(tài)檢查程式庫(kù)

若要發(fā)佈健康狀態(tài)檢查作為程式庫(kù):

寫(xiě)入健康狀態(tài)檢查,將 IHealthCheck 介面當(dāng)做獨(dú)立類別來(lái)實(shí)作。 此類別可能依賴相依性插入 (DI)、類型啟用和具名選項(xiàng)來(lái)存取組態(tài)資料。

使用取用應(yīng)用程式在其 Program.cs 方法中呼叫的參數(shù),來(lái)寫(xiě)入延伸模組。 請(qǐng)考慮下列範(fàn)例健康情況檢查,而此檢查接受 arg1 和 arg2 作為建構(gòu)函式參數(shù):

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

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

arg1:健康情況檢查的整數(shù)資料點(diǎn)。 arg2:健康情況檢查的字串引數(shù)。 name:選用的健康情況檢查名稱。 如果 null,則會(huì)使用預(yù)設(shè)值。 failureStatus:選用的 HealthStatus,其回報(bào)失敗狀態(tài)。 如果為 null,則會(huì)使用 HealthStatus.Unhealthy。 tags:標(biāo)記的選用 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)); } }

健康狀態(tài)檢查發(fā)行者

當(dāng) IHealthCheckPublisher 新增至服務(wù)容器時(shí),健康狀態(tài)檢查系統(tǒng)會(huì)定期執(zhí)行健康狀態(tài)檢查,並呼叫 PublishAsync 傳回結(jié)果。 此處理序適用於推送型健康情況監(jiān)控系統(tǒng)案例,而此案例預(yù)期每個(gè)處理序都會(huì)定期呼叫監(jiān)控系統(tǒng)來(lái)判斷健康情況。

HealthCheckPublisherOptions 可讓您設(shè)定:

Delay:初始延遲會(huì)在應(yīng)用程式啟動(dòng)之後且執(zhí)行 IHealthCheckPublisher 執(zhí)行個(gè)體之前套用。 啟動(dòng)後就會(huì)套用延遲,但不會(huì)套用至後面的反覆項(xiàng)目。 預(yù)設(shè)值是五秒鐘。 Period:IHealthCheckPublisher 執(zhí)行的期間。 預(yù)設(shè)值為 30 秒。 Predicate:如果 Predicate 為 null (預(yù)設(shè)),則健康情況檢查發(fā)行者服務(wù)會(huì)執(zhí)行所有已登錄的健康情況檢查。 若要執(zhí)行一部分的健康狀態(tài)檢查,請(qǐng)?zhí)峁┛珊Y選該組檢查的函式。 每個(gè)期間都會(huì)評(píng)估該述詞。 Timeout:執(zhí)行所有 IHealthCheckPublisher 執(zhí)行個(gè)體之健康情況檢查的逾時(shí)。 若要在沒(méi)有逾時(shí)的情況下執(zhí)行,請(qǐng)使用 InfiniteTimeSpan。 預(yù)設(shè)值為 30 秒。

下列範(fàn)例示範(fàn)健康情況發(fā)行者的配置:

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

HealthCheckPublisherOptions 類別提供屬性來(lái)設(shè)定健康情況檢查發(fā)行者的行為。

下列範(fàn)例會(huì)將健康情況檢查發(fā)行者登錄為單一資料庫(kù),並設(shè)定 HealthCheckPublisherOptions:

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

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

您可以使用相依性插入來(lái)取用健康情況檢查類別內(nèi)特定 Type 的執(zhí)行個(gè)體。 相依性插入適用於將選項(xiàng)或全域設(shè)定插入至健康情況檢查。 使用相依性插入「不」是設(shè)定健康情況檢查的常見(jiàn)案例。 通常,每個(gè)健康情況檢查都是專屬於實(shí)際測(cè)試,並且使用 IHealthChecksBuilder 擴(kuò)充方法進(jìn)行設(shè)定。

下列範(fàn)例顯示可透過(guò)相依性插入來(lái)擷取設(shè)定物件的範(fàn)例健康情況檢查:

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 和健康情況檢查需要新增至服務(wù)容器:

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 會(huì)登錄中介軟體來(lái)處理中介軟體管線中的健康情況檢查要求。 MapHealthChecks 會(huì)登錄健康情況檢查端點(diǎn)。 端點(diǎn)會(huì)與應(yīng)用程式中的其他端點(diǎn)進(jìn)行比對(duì)和執(zhí)行。

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

UseHealthChecks:

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

MapHealthChecks 允許:

對(duì)應(yīng)特定路由或端點(diǎn)以進(jìn)行健康情況檢查。 自訂可存取健康情況檢查端點(diǎn)的 URL 或路徑。 使用不同的路由或設(shè)定來(lái)對(duì)應(yīng)多個(gè)健康情況檢查端點(diǎn)。 多個(gè)端點(diǎn)支援: 針對(duì)不同類型的健康情況檢查或元件啟用不同的端點(diǎn)。 用來(lái)區(qū)分應(yīng)用程式健康情況的不同層面,或?qū)⑻囟ㄔO(shè)定套用至健康情況檢查的子集。 原始程式碼

其他資源

檢視或下載範(fàn)例程式碼 (英文) (如何下載)您可以在 GitHub 上找到此內(nèi)容的來(lái)源,在其中建立和檢閱問(wèn)題和提取要求。 如需詳細(xì)資訊,請(qǐng)參閱我們的參與者指南。

其他資源

事件

加入我們?cè)?FabCon Vegas

3月31日 下午11時(shí) - 4月2日 下午11時(shí)

最終Microsoft Fabric、Power BI、SQL 和 AI 社群主導(dǎo)的活動(dòng)。 2025 年 3 月 31 日至 4 月 2 日。

立即註冊(cè)

本文內(nèi)容

相關(guān)知識(shí)

健康體檢,哪些項(xiàng)目該查
簡(jiǎn)單易行的肌肉骨骼健康保護(hù)方法
生態(tài)環(huán)境部發(fā)佈《“十四五”環(huán)境健康工作規(guī)劃》
報(bào)告稱中國(guó)近九成城市“亞健康”?北京環(huán)境排名靠后
醫(yī)思健康醫(yī)療中心 EC Healthcare Medical Centre
去年以來(lái)江蘇立案生態(tài)環(huán)境民事公益訴訟達(dá)590件
這份心理調(diào)適指南 送給高考後的你們
中華人民共和國(guó)生態(tài)環(huán)境部令(第32號(hào))  排污許可管理辦法
衛(wèi)生部日前發(fā)佈孕産期保健工作管理辦法及規(guī)範(fàn)
中醫(yī)健康管理

網(wǎng)址: ASP.NET Core 中的健康狀態(tài)檢查 http://m.u1s5d6.cn/newsview496090.html

推薦資訊