ASP.NET Core の正常性チェック
作成者: Glenn Condron、Juergen Gutsch
注意
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
ASP.NET Core からは、アプリ インフラストラクチャ コンポーネントの正常性を報告するための正常性チェック ミドルウェアとライブラリが提供されます。
正常性チェックは HTTP エンドポイントとしてアプリによって公開されます。 正常性チェック エンドポイントは、さまざまなリアルタイム監視シナリオに合わせて設定できます。
- 正常性プローブは、アプリの状態を確認する目的でコンテナー オーケストレーターとロード バランサーによって使用できます。 たとえば、正常性チェックで問題が確認された場合、コンテナー オーケストレーターは実行中の展開を停止したり、コンテナーを再起動したりします。 ロード バランサーはアプリの異常に対処するため、問題のあるインスタンスから正常なインスタンスにトラフィック経路を変更することがあります。
- メモリ、ディスク、その他の物理サーバー リソースの使用を監視し、正常性の状態を確認できます。
- 正常性チェックでは、データベースや外部サービス エンドポイントなど、アプリの依存関係をテストし、それらが利用できることと正常に機能していることを確認できます。
正常性チェックは通常、アプリの状態を確認する目的で、外部の監視サービスまたはコンテナー オーケストレーターと共に使用されます。 正常性チェックをアプリに追加する前に、使用する監視システムを決定します。 監視システムからは、作成する正常性チェックの種類とそのエンドポイントの設定方法が指示されます。
基本的な正常性プローブ
多くのアプリでは、アプリが要求を処理できること (活動性) を報告する基本的な正常性チェック構成で十分にアプリの状態を検出できます。
基本の構成では、正常性チェック サービスを登録し、正常性チェック ミドルウェアを呼び出します。このミドルウェアが特定の URL エンドポイントにおける正常性を返します。 既定では、特定の依存関係またはサブシステムをテストする正常性チェックは登録されていません。 正常性エンドポイント URL で応答できる場合、そのアプリは正常であると見なされます。 既定の応答ライターは、プレーンテキストの応答として HealthStatus をクライアントに書き込みます。 HealthStatus
は、HealthStatus.Healthy、HealthStatus.Degraded、または HealthStatus.Unhealthy です。
正常性チェック サービスを Program.cs
の AddHealthChecks に登録します。 MapHealthChecks を呼び出して、正常性チェック エンドポイントを作成します。
次の例では、/healthz
に正常性チェック エンドポイントを作成しています。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/healthz");
app.Run();
Docker の HEALTHCHECK
Docker からは、組み込み HEALTHCHECK
ディレクティブが提供されます。これを使用し、基本的な正常性チェック構成を使用するアプリの状態を確認できます。
HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit
上の例では、curl
を使用して、/healthz
の正常性チェック エンドポイントに対して HTTP 要求を行っています。 curl
は .NET Linux コンテナー イメージには含まれていませんが、必要なパッケージを Dockerfile にインストールすることによって追加できます。 Alpine Linux に基づくイメージを使用するコンテナーでは、curl
の代わりに含まれている wget
を使用できます。
正常性チェックを作成する
正常性チェックは IHealthCheck インターフェイスを実装することで作成されます。 CheckHealthAsync メソッドによって、Healthy
、Degraded
、Unhealthy
のいずれかの正常性を示す HealthCheckResult が返されます。 結果は、構成可能なステータス コードを含むプレーンテキストの応答として書き込まれます。 構成については、「正常性チェック オプション」を参照してください。 HealthCheckResult からは、任意のキーと値のペアを返すこともできます。
次の例は、正常性チェックのレイアウトを示しています。
public class SampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
正常性チェックのロジックが CheckHealthAsync メソッドに配置されています。 前の例では、ダミー変数 isHealthy
が true
に設定されています。 isHealthy
の値が false
に設定されている場合、HealthCheckRegistration.FailureStatus 状態が返されます。
CheckHealthAsync がチェック中に例外をスローした場合、HealthReportEntry.Status が FailureStatus に設定された新しい HealthReportEntry が返されます。 この状態は AddCheck によって定義され (「正常性チェック サービスを登録する」を参照)、チェックに失敗した原因となった内部例外が含まれています。 Description は例外のメッセージに設定されます。
正常性チェック サービスを登録する
正常性チェック サービスを登録するには、Program.cs
で AddCheck を呼び出します。
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>("Sample");
次の例にある AddCheck オーバーロードでは、正常性チェックでエラーが報告されると、レポートにエラー状態 (HealthStatus) が設定されます。 エラー状態が null
(既定) に設定された場合、HealthStatus.Unhealthy が報告されます。 このオーバーロードはライブラリ作成者にとって便利です。この設定に正常性チェック実装が従う場合、正常性チェック エラーが発生したとき、ライブラリによって指示されるエラー状態がアプリによって適用されます。
"タグ" を使用して、正常性チェックをフィルター処理できます。 タグの詳細については、「正常性チェックをフィルター処理する」を参照してください。
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" });
AddCheck では、lambda 関数も実行できます。 この例では、正常性チェックにより常に正常な結果が返されます。
builder.Services.AddHealthChecks()
.AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));
AddTypeActivatedCheck を呼び出して、正常性チェックの実装に引数を渡します。 次の例では、型がアクティブ化された正常性チェックは、コンストラクターに整数と文字列を受け取ります。
public class SampleHealthCheckWithArgs : IHealthCheck
{
private readonly int _arg1;
private readonly string _arg2;
public SampleHealthCheckWithArgs(int arg1, string arg2)
=> (_arg1, _arg2) = (arg1, arg2);
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
// ...
return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
}
}
上記の正常性チェックを登録するには、整数と文字列を引数として渡して AddTypeActivatedCheck
を呼び出します。
builder.Services.AddHealthChecks()
.AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" },
args: new object[] { 1, "Arg" });
正常性チェックのルーティングを使用する
Program.cs
で、エンドポイントの URL または相対パスを使用して、エンドポイント ビルダーで MapHealthChecks
を呼び出します。
app.MapHealthChecks("/healthz");
ホストが必要
RequireHost
を呼び出して、正常性チェック エンドポイントに許可されている 1 つ以上のホストを指定します。 ホストは、punycode ではなく Unicode にする必要があります。また、ポートを含めることができます。 コレクションが指定されていない場合は、任意のホストを使用できます。
app.MapHealthChecks("/healthz")
.RequireHost("www.contoso.com:5001");
特定のポートでのみ応答するように正常性チェック エンドポイントを制限するには、RequireHost
の呼び出しでポートを指定します。 この方法は通常、サービスを監視するためのポートを公開する目的で、コンテナー環境で使用されます。
app.MapHealthChecks("/healthz")
.RequireHost("*:5001");
警告
HttpRequest.Host、RequireHost などのホスト ヘッダーに依存する API は、クライアントによるスプーフィングの対象になる可能性があります。
ホストとポートのスプーフィングを防ぐには、次のいずれかの方法を使用します。
- ポートがチェックされる場所で HttpContext.Connection (ConnectionInfo.LocalPort) を使用します。
- ホスト フィルタリングを採用します。
承認されていないクライアントがポートをスプーフィングするのを防ぐには、RequireAuthorization を呼び出します。
app.MapHealthChecks("/healthz")
.RequireHost("*:5001")
.RequireAuthorization();
詳細については、「RequireHost とルートが一致するホスト」を参照してください。
承認が必要
RequireAuthorization を呼び出して、正常性チェック要求エンドポイントで承認ミドルウェアを実行します。 RequireAuthorization
のオーバーロードには 1 つ以上の承認ポリシーを使用できます。 ポリシーが指定されていない場合は、既定の承認ポリシーが使用されます。
app.MapHealthChecks("/healthz")
.RequireAuthorization();
クロスオリジン要求 (CORS) の有効化
ブラウザーから手動で正常性チェックを実行することは一般的なシナリオではありませんが、正常性チェック エンドポイントで RequireCors
を呼び出して CORS ミドルウェアを有効にすることができます。 RequireCors
のオーバーロードには、CORS ポリシー ビルダーのデリゲート (CorsPolicyBuilder
) またはポリシー名を使用できます。 詳細については、「ASP.NET Core でクロスオリジン要求 (CORS) を有効にする」を参照してください。
正常性チェック オプション
HealthCheckOptions では、正常性チェックの動作をカスタマイズできます。
正常性チェックをフィルター処理する
既定では、正常性チェック ミドルウェアによって、登録済みの正常性チェックがすべて実行されます。 正常性チェックのサブセットを実行するには、Predicate オプションにブール値を返す関数を指定します。
次の例では、正常性チェックのフィルター処理を行い、sample
タグが付けられているものだけが実行されるようにします。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});
HTTP 状態コードをカスタマイズする
ResultStatusCodes を使用し、HTTP 状態コードに対する正常性状態のマッピングをカスタマイズします。 次の StatusCodes 代入はミドルウェアによって使用される既定値です。 要件に合わせて状態コード値を変更します。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
キャッシュ ヘッダーを非表示にする
AllowCachingResponses によって、応答キャッシュを禁止する目的で、正常性チェック ミドルウェアによって HTTP ヘッダーがプローブ応答に追加されるかどうかが制御されます。 値が false
(既定) の場合、応答キャッシュを禁止する目的で、ミドルウェアによってヘッダー Cache-Control
、Expires
、Pragma
が設定またはオーバーライドされます。 値が true
の場合、応答のキャッシュ ヘッダーがミドルウェアによって変更されることはありません。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
AllowCachingResponses = true
});
出力をカスタマイズする
正常性チェック レポートの出力をカスタマイズするには、HealthCheckOptions.ResponseWriter プロパティを、応答の書き込み先のデリゲートに設定します。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResponseWriter = WriteResponse
});
既定の委任では、文字列値 HealthReport.Status
を含む、最小のプレーンテキスト応答が書き込まれます。 次のカスタム デリゲートでは、System.Text.Json を使用してカスタム JSON 応答が出力されます。
private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions { Indented = true };
using var memoryStream = new MemoryStream();
using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
{
jsonWriter.WriteStartObject();
jsonWriter.WriteString("status", healthReport.Status.ToString());
jsonWriter.WriteStartObject("results");
foreach (var healthReportEntry in healthReport.Entries)
{
jsonWriter.WriteStartObject(healthReportEntry.Key);
jsonWriter.WriteString("status",
healthReportEntry.Value.Status.ToString());
jsonWriter.WriteString("description",
healthReportEntry.Value.Description);
jsonWriter.WriteStartObject("data");
foreach (var item in healthReportEntry.Value.Data)
{
jsonWriter.WritePropertyName(item.Key);
JsonSerializer.Serialize(jsonWriter, item.Value,
item.Value?.GetType() ?? typeof(object));
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
return context.Response.WriteAsync(
Encoding.UTF8.GetString(memoryStream.ToArray()));
}
正常性チェック API には、複雑な JSON の戻り値の形式に対する組み込みのサポートが用意されていません。この形式は、選択した監視システムに固有のものであるためです。 必要に応じて、上記の例の応答をカスタマイズします。 System.Text.Json
を使用した JSON シリアル化の詳細については、.NET で JSON をシリアル化および逆シリアル化する方法に関する記事をご覧ください。
データベース プローブ
正常性チェックでは、データベースが通常どおり応答しているかどうかを示すブール値テストとして実行されるよう、データベース クエリを指定できます。
ASP.NET Core アプリ用の正常性チェック ライブラリ AspNetCore.Diagnostics.HealthChecks
には、SQL Server データベースに対して実行される正常性チェックが含まれています。 AspNetCore.Diagnostics.HealthChecks
によってデータベースに対して SELECT 1
クエリが実行され、データベースへの接続が正常であることが確認されます。
警告
クエリでデータベース接続を確認するとき、すぐに返されるクエリを選択します。 このクエリ手法には、データベースをオーバーロードし、そのパフォーマンスを低下させるというリスクがあります。 ほとんどの場合、テスト クエリは実行する必要がありません。 データベースに正常に接続できれば十分です。 クエリを実行する必要があれば、SELECT 1
など、単純な SELECT クエリを選択してください。
この SQL Server 正常性チェックを使用するには、AspNetCore.HealthChecks.SqlServer
NuGet パッケージへのパッケージ参照を含めます。 次の例では、SQL Server 正常性チェックを登録します。
var conStr = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(conStr))
{
throw new InvalidOperationException(
"Could not find a connection string named 'DefaultConnection'.");
}
builder.Services.AddHealthChecks()
.AddSqlServer(conStr);
Note
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
Entity Framework Core DbContext プローブ
DbContext
チェックでは、EF CoreDbContext
に対して構成されているデータベースとアプリとが通信できることが確認されます。 DbContext
チェックは、次のようなアプリでサポートされています。
- Entity Framework (EF) Core を使用する。
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
NuGet パッケージへのパッケージ参照を含めます。
AddDbContextCheck によって DbContext の正常性チェックが登録されます。 DbContext
は TContext
としてメソッドに指定されます。 オーバーロードはエラー状態、タグ、カスタム テスト クエリの設定に利用できます。
既定では:
DbContextHealthCheck
は、EF Core のCanConnectAsync
メソッドを呼び出します。AddDbContextCheck
メソッドのオーバーロードを使用して正常性を確認するときに実行される操作をカスタマイズできます。- 正常性チェックの名前は
TContext
型の名前になります。
次の例では、DbContext
と、これに関連付けられている DbContextHealthCheck
を登録します。
builder.Services.AddDbContext<SampleDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddHealthChecks()
.AddDbContextCheck<SampleDbContext>();
対応性と活動性に区分されるプローブ
一部のホスティング シナリオでは、2 つのアプリ状態を区別する一組の正常性チェックが使用されます。
- "対応性" は、アプリが通常どおり実行されているが、要求を受け取る準備ができていないのか、あるいはそうではないのかを示します。
- "活動性" は、アプリがクラッシュしたため、再起動する必要があるのかどうかを示します。
次に例を示します。アプリでは、大きな構成ファイルをダウンロードしないと、要求を処理する準備ができません。 初回ダウンロードに失敗した場合、アプリを再起動することは望みません。アプリはファイルのダウンロードを数回再試行する可能性があるためです。 liveness probe を使用し、プロセスの活動性を記述します。他のチェックは実行されません。 また、構成ファイルのダウンロードが完了する前は、要求がアプリに送信されないようにします。 "対応性プローブ" を使用し、ダウンロードが成功し、要求を受け取る準備がアプリにできるまで、"準備できていない" 状態を示します。
次のバックグラウンド タスクでは、15 秒ほどかかるスタートアップ プロセスをシミュレートします。 完了すると、このタスクによって StartupHealthCheck.StartupCompleted
プロパティが true に設定されます。
public class StartupBackgroundService : BackgroundService
{
private readonly StartupHealthCheck _healthCheck;
public StartupBackgroundService(StartupHealthCheck healthCheck)
=> _healthCheck = healthCheck;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Simulate the effect of a long-running task.
await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);
_healthCheck.StartupCompleted = true;
}
}
StartupHealthCheck
は、実行時間の長いスタートアップ タスクの完了をレポートし、バックグラウンド サービスによって設定される StartupCompleted
プロパティを公開します。
public class StartupHealthCheck : IHealthCheck
{
private volatile bool _isReady;
public bool StartupCompleted
{
get => _isReady;
set => _isReady = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
if (StartupCompleted)
{
return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
}
return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
}
}
ホステッド サービスと共に Program.cs
で正常性チェックが AddCheck に登録されます。 ホステッド サービスでは正常性チェックにプロパティを設定する必要があるため、正常性チェックはシングルトンとしてサービス コンテナーにも登録されます。
builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();
builder.Services.AddHealthChecks()
.AddCheck<StartupHealthCheck>(
"Startup",
tags: new[] { "ready" });
2 つの異なる正常性チェック エンドポイントを作成するには、MapHealthChecks
を 2 回呼び出します。
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
Predicate = _ => false
});
前の例では、次の正常性チェック エンドポイントを作成しています。
- 対応性チェックの場合は
/healthz/ready
。 対応性チェックでは、ready
タグが付けられているものに正常性チェックが絞り込まれます。 - 活動性チェックの場合は
/healthz/live
。 この活動性チェックでは、HealthCheckOptions.Predicate デリゲートでfalse
を返すことによって、すべての正常性チェックを除外します。 正常性チェックのフィルター処理の詳細については、この記事の「正常性チェックをフィルター処理する」を参照してください。
スタートアップ タスクが完了する前に、/healthz/ready
エンドポイントから Unhealthy
状態がレポートされます。 スタートアップ タスクが完了したら、このエンドポイントから Healthy
状態がレポートされます。 /healthz/live
エンドポイントは、すべてのチェックを除外し、すべての呼び出しに対して Healthy
状態をレポートします。
Kubernetes の例
対応性チェックと活動性チェックを使い分けることは、Kubernetes などの環境で便利です。 Kubernetes では、要求を受け入れる前に、基礎をなすデータベースの可用性テストなど、時間のかかるスタートアップ作業の実行がアプリに要求されることがあります。 別個のチェックを利用することで、アプリは機能しているがまだ準備ができていないか、あるいはアプリが起動に失敗したかをオーケストレーターは区別できます。 Kubernetes の対応性プローブと活動性プローブに関する詳細については、Kubernetes ドキュメントの「Configure Liveness and Readiness Probes」 (活動性プローブと対応性プローブを設定する) を参照してください。
次の例では、Kubernetes 対応性プローブの構成を確認できます。
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /healthz/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
正常性チェック ライブラリを配布する
正常性チェックをライブラリとして配布するには:
スタンドアロン クラスとして IHealthCheck インターフェイスを実装する正常性チェックを記述します。 このクラスは、設定データにアクセスする目的で依存関係挿入 (DI)、型のアクティブ化、名前付きオプションに依存できます。
拡張メソッドを記述します。拡張メソッドを使用するアプリがその
Program.cs
メソッドで呼び出すパラメーターを指定します。arg1
とarg2
をコンストラクター パラメーターとして受け取る、次の正常性チェックの例を考えてみましょう。public SampleHealthCheckWithArgs(int arg1, string arg2) => (_arg1, _arg2) = (arg1, arg2);
先のシグネチャは、正常性チェック プローブ ロジックを処理するためには、正常性チェックにカスタム データが必要であることを示しています。 正常性チェックが拡張メソッドに登録されたときに正常性チェック インスタンスを作成するための委任にデータが提供されます。 次の例では、呼び出し元によって以下が指定されます。
arg1
: 正常性チェックの整数データ ポイント。arg2
: 正常性チェックの文字列引数。name
: 正常性チェック名 (省略可能)。null
の場合、既定値が使用されます。failureStatus
: エラー状態に対してレポートされる HealthStatus (省略可能)。null
の場合、HealthStatus.Unhealthy が使用されます。tags
: タグのIEnumerable<string>
コレクション (省略可能)。
public static class SampleHealthCheckBuilderExtensions { private const string DefaultName = "Sample"; public static IHealthChecksBuilder AddSampleHealthCheck( this IHealthChecksBuilder healthChecksBuilder, int arg1, string arg2, string? name = null, HealthStatus? failureStatus = null, IEnumerable<string>? tags = default) { return healthChecksBuilder.Add( new HealthCheckRegistration( name ?? DefaultName, _ => new SampleHealthCheckWithArgs(arg1, arg2), failureStatus, tags)); } }
正常性チェック パブリッシャー
サービス コンテナーに IHealthCheckPublisher が追加されると、正常性チェック システムにより定期的に正常性チェックが実行され、結果と共に PublishAsync が呼び出されます。 このプロセスは、正常性を判断する目的で監視システムを定期的に呼び出すことを各プロセスに求めるプッシュベースの監視システム シナリオで便利です。
HealthCheckPublisherOptions を使うと次を設定できます。
- Delay:アプリが起動した後、IHealthCheckPublisher インスタンスを実行する前に適用される初期遅延です。 遅延はスタートアップ時に一度だけ適用され、後の繰り返しには適用されません。 既定値は 5 秒です。
- Period:IHealthCheckPublisher を実行する期間です。 既定値は 30 秒です。
- Predicate:Predicate が
null
(既定値) の場合、正常性チェック パブリッシャー サービスにより登録済みのすべての正常性チェックが実行されます。 正常性チェックのサブセットを実行するには、チェックのセットをフィルター処理する関数を指定します。 述語は期間ごとに評価されます。 - Timeout:すべての IHealthCheckPublisher インスタンスに対する正常性チェックの実行のタイムアウトです。 タイムアウトなしで実行するには InfiniteTimeSpan を使います。 既定値は 30 秒です。
次の例は、正常性パブリッシャーのレイアウトを示しています。
public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
// ...
}
else
{
// ...
}
return Task.CompletedTask;
}
}
HealthCheckPublisherOptions クラスには、正常性チェック パブリッシャーの動作を構成するためのプロパティが用意されています。
次の例では、正常性チェック パブリッシャーをシングルトンとして登録し、HealthCheckPublisherOptions を構成します。
builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});
builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();
AspNetCore.Diagnostics.HealthChecks
:
- Application Insights など、いくつかのシステム用の発行元を含みます。
- Microsoft によって保守もサポートも行われて "いません"。
個々の正常性チェック
Delay
および Period
は、それぞれの HealthCheckRegistration に個別に設定できます。 これは、いくつかの正常性チェックを HealthCheckPublisherOptions で設定されている期間とは異なるレートで実行したい場合に便利です。
次のコードは、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();
依存関係の挿入と正常性チェック
正常性チェック クラス内の特定の Type
のインスタンスを使用するために、依存関係の挿入を使用することができます。 依存関係の挿入は、正常性チェックにオプションまたはグローバル構成を挿入する場合に役立ちます。 依存関係の挿入を使用することは、正常性チェックを構成するための一般的なシナリオでは "ありません"。 通常、各正常性チェックは実際のテストに完全に固有のものであり、IHealthChecksBuilder
拡張メソッドを使用して構成されます。
次の例は、依存関係の挿入を使用して構成オブジェクトを取得する正常性チェックのサンプルを示したものです。
public class SampleHealthCheckWithDI : IHealthCheck
{
private readonly SampleHealthCheckWithDiConfig _config;
public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
=> _config = config;
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// use _config ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
SampleHealthCheckWithDiConfig
と正常性チェックをサービス コンテナーに追加する必要があります。
builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheckWithDI>(
"With Dependency Injection",
tags: new[] { "inject" });
UseHealthChecks と MapHealthChecks
呼び出し元が正常性チェックにアクセスできるようにするには、次の 2 つの方法があります。
- UseHealthChecks は、ミドルウェア パイプラインで正常性チェック要求を処理するためのミドルウェアを登録します。
- MapHealthChecks は、正常性チェック エンドポイントを登録します。 エンドポイントは、アプリ内の他のエンドポイントと合わせてマッチされ実行されます。
UseHealthChecks
上で MapHealthChecks
を使用する利点は、認可のようなエンドポイント認識ミドルウェアを使用し、マッチ ポリシーをより細かい粒度で制御できる点です。 MapHealthChecks
上で UseHealthChecks
を使用する主な利点は、ミドルウェア パイプラインで正常性チェックが実行される場所を正確に制御できることです。
- 要求が正常性チェック エンドポイントとマッチすると、パイプラインを終了させます。 ショートサーキットはログやその他のミドルウェアなどの不要な作業を防ぐため、多くの場合に望ましいものです。
- 主に、パイプラインで正常性チェック ミドルウェアを構成するために使用されます。
null
または空のPathString
を持つポート上の任意のパスとマッチできます。 指定したポートに対して行われた任意の要求に対して正常性チェックの実行を許可します。- ソース コード
MapHealthChecks は次のことを許可します。
- ShortCircuit を呼び出して、要求が正常性チェック エンドポイントとマッチした場合のパイプラインの終了。 たとえば、「
app.MapHealthChecks("/healthz").ShortCircuit();
」のように入力します。 詳しくは、「ルーティング後のミドルウェアのショートサーキット」を参照してください。 - 正常性チェック用の特定のルートまたはエンドポイントのマッピング。
- 正常性チェック エンドポイントにアクセスできる URL またはパスのカスタマイズ。
- ルートまたは構成が異なる複数の正常性チェック エンドポイントのマッピング。 複数エンドポイントのサポート:
- さまざまな種類の正常性チェックまたはコンポーネントに対して個別のエンドポイントを有効にします。
- アプリの正常性のさまざまな側面を区別したり、正常性チェックのサブセットに特定の構成を適用したりするために使用されます。
- ソース コード
その他のリソース
- サンプル コードを表示またはダウンロードします (ダウンロード方法)。
注意
この記事は部分的に人工知能を活用して作成しました。 公開する前に作成者が内容を確認し、必要に応じて修正しました。 AI によって生成されたコンテンツを Microsoft Learn で使用するための原則に関するページを参照してください。
ASP.NET Core からは、アプリ インフラストラクチャ コンポーネントの正常性を報告するための正常性チェック ミドルウェアとライブラリが提供されます。
正常性チェックは HTTP エンドポイントとしてアプリによって公開されます。 正常性チェック エンドポイントは、さまざまなリアルタイム監視シナリオに合わせて設定できます。
- 正常性プローブは、アプリの状態を確認する目的でコンテナー オーケストレーターとロード バランサーによって使用できます。 たとえば、正常性チェックで問題が確認された場合、コンテナー オーケストレーターは実行中の展開を停止したり、コンテナーを再起動したりします。 ロード バランサーはアプリの異常に対処するため、問題のあるインスタンスから正常なインスタンスにトラフィック経路を変更することがあります。
- メモリ、ディスク、その他の物理サーバー リソースの使用を監視し、正常性の状態を確認できます。
- 正常性チェックでは、データベースや外部サービス エンドポイントなど、アプリの依存関係をテストし、それらが利用できることと正常に機能していることを確認できます。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
サンプル アプリには、この記事で説明されているシナリオの例が含まれています。 所与のシナリオに対してサンプル アプリを実行するには、コマンド シェルでプロジェクトのフォルダーから dotnet run コマンドを使用します。 サンプル アプリの詳しい使用方法については、サンプル アプリの README.md
ファイルとこの記事のシナリオ説明を参照してください。
前提条件
正常性チェックは通常、アプリの状態を確認する目的で、外部の監視サービスまたはコンテナー オーケストレーターと共に使用されます。 正常性チェックをアプリに追加する前に、使用する監視システムを決定します。 監視システムからは、作成する正常性チェックの種類とそのエンドポイントの設定方法が指示されます。
Microsoft.AspNetCore.Diagnostics.HealthChecks
パッケージは、ASP.NET Core アプリに対して暗黙的に参照されます。 Entity Framework Core を使用して正常性チェックを実行するには、Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
パッケージへの参照を追加します。
サンプル アプリからは、いくつかのシナリオで正常性チェックを実演するスタートアップ コードが提供されます。 データベース プローブ シナリオでは、AspNetCore.Diagnostics.HealthChecks
を使用して、データベース接続の正常性をチェックします。 DbContext プローブ シナリオでは、EF CoreDbContext
を使用して、データベースがチェックされます。 データベース シナリオを探索するために、サンプル アプリでは次のことが行われます:
- データベースを作成して、
appsettings.json
ファイルにその接続文字列を指定します。 - そのプロジェクト ファイルに次のパッケージ参照が含まれています:
Note
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
もう 1 つの正常性チェックのシナリオでは、1 つの管理ポートに正常性チェックを絞り込む方法が実演されます。 このサンプル アプリでは、管理 URL と管理ポートを含む Properties/launchSettings.json
ファイルを作成する必要があります。 詳細については、「ポート別のフィルター処理」セクションを参照してください。
基本的な正常性プローブ
多くのアプリでは、アプリが要求を処理できること (活動性) を報告する基本的な正常性チェック構成で十分にアプリの状態を検出できます。
基本の構成では、正常性チェック サービスを登録し、正常性チェック ミドルウェアを呼び出します。このミドルウェアが特定の URL エンドポイントにおける正常性を返します。 既定では、特定の依存関係またはサブシステムをテストする正常性チェックは登録されていません。 正常性エンドポイント URL で応答できる場合、そのアプリは正常であると見なされます。 既定の応答ライターによって、プレーンテキストの応答として状態 (HealthStatus) がクライアントに書き込まれます。このとき、状態として HealthStatus.Healthy、HealthStatus.Degraded、または HealthStatus.Unhealthy が示されます。
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 Startup.Configure
で MapHealthChecks
を呼び出して、正常性チェック エンドポイントを作成します。
サンプル アプリでは、正常性チェック エンドポイントは /health
で作成されます (BasicStartup.cs
)。
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
サンプル アプリを使用して基本的な構成シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario basic
Docker の例
Docker からは、組み込み HEALTHCHECK
ディレクティブが提供されます。これを使用し、基本的な正常性チェック構成を使用するアプリの状態を確認できます。
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
正常性チェックを作成する
正常性チェックは IHealthCheck インターフェイスを実装することで作成されます。 CheckHealthAsync メソッドによって、Healthy
、Degraded
、Unhealthy
のいずれかの正常性を示す HealthCheckResult が返されます。 この結果が構成可能な状態コードと共にプレーンテキストの応答として書き込まれます (構成の説明は「正常性チェック オプション」セクションにあります)。 HealthCheckResult からは、任意のキーと値のペアを返すこともできます。
次の ExampleHealthCheck
クラスからは、正常性チェックのレイアウトがどのようなものかがわかります。 正常性チェックのロジックが CheckHealthAsync
メソッドに配置されています。 次の例では、ダミー変数 healthCheckResultHealthy
が true
に設定されます。 healthCheckResultHealthy
の値が false
に設定されている場合、HealthCheckRegistration.FailureStatus 状態が返されます。
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(context.Registration.FailureStatus,
"An unhealthy result."));
}
}
チェック中に CheckHealthAsync から例外がスローされた場合、新しい HealthReportEntry が、その HealthReportEntry.Status が FailureStatus に設定された状態で返されます。これは、AddCheck によって定義され (「正常性チェック サービスを登録する」セクションを参照)、最初にチェックの失敗の原因となった内部例外が含まれます。 Description は例外のメッセージに設定されます。
正常性チェック サービスを登録する
Startup.ConfigureServices
の AddCheck によって ExampleHealthCheck
型が正常性チェック サービスに追加されます。
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
次の例にある AddCheck オーバーロードでは、正常性チェックでエラーが報告されると、レポートにエラー状態 (HealthStatus) が設定されます。 エラー状態が null
(既定) に設定された場合、HealthStatus.Unhealthy が報告されます。 このオーバーロードはライブラリ作成者にとって便利です。この設定に正常性チェック実装が従う場合、正常性チェック エラーが発生したとき、ライブラリによって指示されるエラー状態がアプリによって適用されます。
タグを使用し、正常性チェックをフィルター処理できます (詳細は「正常性チェックをフィルター処理する」セクションにあります)。
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck では、lambda 関数も実行できます。 次の例では、正常性チェック名に「Example
」が指定されいます。このチェックでは状態として常に正常が返されます。
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
AddTypeActivatedCheck を呼び出して、正常性チェックの実装に引数を渡します。 次の例では、TestHealthCheckWithArgs
は CheckHealthAsync の呼び出し時に使用する整数と文字列を受け入れます。
private class TestHealthCheckWithArgs : IHealthCheck
{
public TestHealthCheckWithArgs(int i, string s)
{
I = i;
S = s;
}
public int I { get; set; }
public string S { get; set; }
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
CancellationToken cancellationToken = default)
{
...
}
}
TestHealthCheckWithArgs
は実装に渡された整数と文字列を使用して AddTypeActivatedCheck
を呼び出すことによって登録されます。
services.AddHealthChecks()
.AddTypeActivatedCheck<TestHealthCheckWithArgs>(
"test",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" },
args: new object[] { 5, "string" });
正常性チェックのルーティングを使用する
Startup.Configure
で、エンドポイントの URL または相対パスを使用して、エンドポイント ビルダーで MapHealthChecks
を呼び出します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
ホストが必要
RequireHost
を呼び出して、正常性チェック エンドポイントに許可されている 1 つ以上のホストを指定します。 ホストは、punycode ではなく Unicode にする必要があります。また、ポートを含めることができます。 コレクションが指定されていない場合は、任意のホストを使用できます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});
詳細については、「ポート別のフィルター処理」セクションを参照してください。
承認が必要
RequireAuthorization
を呼び出して、正常性チェック要求エンドポイントで承認ミドルウェアを実行します。 RequireAuthorization
のオーバーロードには 1 つ以上の承認ポリシーを使用できます。 ポリシーが指定されていない場合は、既定の承認ポリシーが使用されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireAuthorization();
});
クロスオリジン要求 (CORS) の有効化
ブラウザーから手動で正常性チェックを実行することは一般的な使用シナリオではありませんが、正常性チェック エンドポイントで RequireCors
を呼び出して CORS ミドルウェアを有効にすることができます。 RequireCors
のオーバーロードには、CORS ポリシー ビルダーのデリゲート (CorsPolicyBuilder
) またはポリシー名を使用できます。 ポリシーが指定されていない場合は、既定の CORS ポリシーが使用されます。 詳細については、「ASP.NET Core でクロスオリジン要求 (CORS) を有効にする」を参照してください。
正常性チェック オプション
HealthCheckOptions では、正常性チェックの動作をカスタマイズできます。
正常性チェックをフィルター処理する
既定では、正常性チェック ミドルウェアでは、登録されている正常性チェックがすべて実行されます。 正常性チェックのサブセットを実行するには、Predicate オプションにブール値を返す関数を指定します。 次の例では、関数の条件文にあるそのタグ (bar_tag
) により Bar
正常性チェックが除外されます。true
は、正常性チェックの Tags プロパティが foo_tag
か baz_tag
に一致した場合にのみ返されます。
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
によって 'Bar' 正常性チェックが除外されます。 Foo と Baz のみが実行されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
});
HTTP 状態コードをカスタマイズする
ResultStatusCodes を使用し、HTTP 状態コードに対する正常性状態のマッピングをカスタマイズします。 次の StatusCodes 代入はミドルウェアによって使用される既定値です。 要件に合わせて状態コード値を変更します。
Startup.Configure
の場合:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
});
キャッシュ ヘッダーを非表示にする
AllowCachingResponses によって、応答キャッシュを禁止する目的で、正常性チェック ミドルウェアによって HTTP ヘッダーがプローブ応答に追加されるかどうかが制御されます。 値が false
(既定) の場合、応答キャッシュを禁止する目的で、ミドルウェアによってヘッダー Cache-Control
、Expires
、Pragma
が設定またはオーバーライドされます。 値が true
の場合、応答のキャッシュ ヘッダーがミドルウェアによって変更されることはありません。
Startup.Configure
の場合:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = true
});
});
出力をカスタマイズする
Startup.Configure
で、HealthCheckOptions.ResponseWriter オプションを、応答を書き込むためのデリゲートに設定します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
});
既定の委任では、文字列値 HealthReport.Status
を含む、最小のプレーンテキスト応答が書き込まれます。 次のカスタム デリゲートでは、カスタム JSON 応答が出力されます。
サンプル アプリの最初の例は、System.Text.Json の使用方法を示しています。
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions
{
Indented = true
};
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartObject();
writer.WriteString("status", result.Status.ToString());
writer.WriteStartObject("results");
foreach (var entry in result.Entries)
{
writer.WriteStartObject(entry.Key);
writer.WriteString("status", entry.Value.Status.ToString());
writer.WriteString("description", entry.Value.Description);
writer.WriteStartObject("data");
foreach (var item in entry.Value.Data)
{
writer.WritePropertyName(item.Key);
JsonSerializer.Serialize(
writer, item.Value, item.Value?.GetType() ??
typeof(object));
}
writer.WriteEndObject();
writer.WriteEndObject();
}
writer.WriteEndObject();
writer.WriteEndObject();
}
var json = Encoding.UTF8.GetString(stream.ToArray());
return context.Response.WriteAsync(json);
}
}
2 番目の例では、Newtonsoft.Json
の使用方法を示します。
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json";
var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
return context.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
サンプル アプリでは、CustomWriterStartup.cs
の SYSTEM_TEXT_JSON
プリプロセッサ ディレクティブをコメント アウトして、Newtonsoft.Json
バージョンの WriteResponse
を有効にします。
正常性チェック API には、複雑な JSON の戻り値の形式に対する組み込みのサポートが用意されていません。この形式は、選択した監視システムに固有のものであるためです。 必要に応じて、上記の例の応答をカスタマイズします。 System.Text.Json
を使用した JSON シリアル化の詳細については、.NET で JSON をシリアル化および逆シリアル化する方法に関する記事をご覧ください。
データベース プローブ
正常性チェックでは、データベースが通常どおり応答しているかどうかを示すブール値テストとして実行されるよう、データベース クエリを指定できます。
このサンプル アプリでは、ASP.NET Core アプリ用の正常性チェック ライブラリ AspNetCore.Diagnostics.HealthChecks
を使用して、SQL Server データベースの正常性チェックを実行します。 AspNetCore.Diagnostics.HealthChecks
によってデータベースに対して SELECT 1
クエリが実行され、データベースへの接続が正常であることが確認されます。
警告
クエリでデータベース接続を確認するとき、すぐに返されるクエリを選択します。 このクエリ手法には、データベースをオーバーロードし、そのパフォーマンスを低下させるというリスクがあります。 ほとんどの場合、テスト クエリは実行する必要がありません。 データベースに正常に接続できれば十分です。 クエリを実行する必要があれば、SELECT 1
など、単純な SELECT クエリを選択してください。
AspNetCore.HealthChecks.SqlServer
へのパッケージ参照を含めます。
サンプル アプリの appsettings.json
ファイルに有効なデータベース接続文字列を指定します。 このアプリでは HealthCheckSample
という名前の SQL Server データベースが使用されます。
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"IncludeScopes": "true"
}
},
"AllowedHosts": "*"
}
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 サンプル アプリでは、データベースの接続文字列 (DbHealthStartup.cs
) を利用して AddSqlServer
メソッドを呼び出します。
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
サンプル アプリを使用してデータベース プローブ シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario db
Note
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
Entity Framework Core DbContext プローブ
DbContext
チェックでは、EF CoreDbContext
に対して構成されているデータベースとアプリとが通信できることが確認されます。 DbContext
チェックは、次のようなアプリでサポートされています。
- Entity Framework (EF) Core を使用する。
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
へのパッケージ参照を含めます。
AddDbContextCheck<TContext>
によって DbContext
の正常性チェックが登録されます。 DbContext
は TContext
としてメソッドに指定されます。 オーバーロードはエラー状態、タグ、カスタム テスト クエリの設定に利用できます。
既定では:
DbContextHealthCheck
は、EF Core のCanConnectAsync
メソッドを呼び出します。AddDbContextCheck
メソッドのオーバーロードを使用して正常性を確認するときに実行される操作をカスタマイズできます。- 正常性チェックの名前は
TContext
型の名前になります。
サンプル アプリでは、AppDbContext
が AddDbContextCheck
に提供され、Startup.ConfigureServices
でサービスとして登録されます (DbContextHealthStartup.cs
)。
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
サンプル アプリを利用して DbContext
プローブ シナリオを実行するには、接続文字列によって指定されるデータベースが SQL Server インスタンスに存在しないことを確認します。 データベースが存在する場合、それを削除します。
コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario dbcontext
アプリの実行後、ブラウザーで /health
エンドポイントに要求することで正常性状態を確認します。 データベースと AppDbContext
は存在しません。そこで、アプリによって次の応答が返されます。
Unhealthy
サンプル アプリにデータベースを作成させます。 /createdatabase
に要求を行います。 アプリからの応答は次のようになります。
Creating the database...
Done!
Navigate to /health to see the health status.
/health
エンドポイントに要求を行います。 データベースとコンテキストが存在します。そのため、アプリによって次の応答が返されます。
Healthy
サンプル アプリにデータベースを削除させます。 /deletedatabase
に要求を行います。 アプリからの応答は次のようになります。
Deleting the database...
Done!
Navigate to /health to see the health status.
/health
エンドポイントに要求を行います。 アプリから異常という応答が返されます。
Unhealthy
対応性と活動性に区分されるプローブ
一部のホスティング シナリオでは、2 つのアプリ状態を区別する一組の正常性チェックが使用されます。
- "対応性" は、アプリが通常どおり実行されているが、要求を受け取る準備ができていないのか、あるいはそうではないのかを示します。
- "活動性" は、アプリがクラッシュしたため、再起動する必要があるのかどうかを示します。
次に例を示します。アプリでは、大きな構成ファイルをダウンロードしないと、要求を処理する準備ができません。 初回ダウンロードに失敗した場合、アプリを再起動することは望みません。アプリはファイルのダウンロードを数回再試行する可能性があるためです。 liveness probe を使用し、プロセスの活動性を記述します。他のチェックは実行されません。 また、構成ファイルのダウンロードが完了する前は、要求がアプリに送信されないようにします。 "対応性プローブ" を使用し、ダウンロードが成功し、要求を受け取る準備がアプリにできるまで、"準備できていない" 状態を示します。
サンプル アプリには、ホステッド サービスの長時間実行スタートアップ タスクの完了を報告する正常性チェックが含まれています。 StartupHostedServiceHealthCheck
によって StartupTaskCompleted
というプロパティが公開されます。ホステッド サービスでは長時間実行タスクの完了時にこのプロパティを true
に設定できます (StartupHostedServiceHealthCheck.cs
)。
public class StartupHostedServiceHealthCheck : IHealthCheck
{
private volatile bool _startupTaskCompleted = false;
public string Name => "slow_dependency_check";
public bool StartupTaskCompleted
{
get => _startupTaskCompleted;
set => _startupTaskCompleted = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
if (StartupTaskCompleted)
{
return Task.FromResult(
HealthCheckResult.Healthy("The startup task is finished."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("The startup task is still running."));
}
}
長時間実行バックグラウンド タスクはホステッド サービスによって開始されます (Services/StartupHostedService
)。 タスクが終わると、StartupHostedServiceHealthCheck.StartupTaskCompleted
が true
に設定されます。
public class StartupHostedService : IHostedService, IDisposable
{
private readonly int _delaySeconds = 15;
private readonly ILogger _logger;
private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;
public StartupHostedService(ILogger<StartupHostedService> logger,
StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
{
_logger = logger;
_startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is starting.");
// Simulate the effect of a long-running startup task.
Task.Run(async () =>
{
await Task.Delay(_delaySeconds * 1000);
_startupHostedServiceHealthCheck.StartupTaskCompleted = true;
_logger.LogInformation("Startup Background Service has started.");
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is stopping.");
return Task.CompletedTask;
}
public void Dispose()
{
}
}
ホステッド サービスと共に Startup.ConfigureServices
で正常性チェックが AddCheck に登録されます。 ホステッド サービスでは正常性チェックにプロパティを設定する必要があるため、正常性チェックはサービス コンテナーにも登録されます (LivenessProbeStartup.cs
)。
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();
services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。 サンプル アプリでは、正常性チェック エンドポイントは次の場所に作成されます。
- 対応性チェックの場合は
/health/ready
。 対応性チェックでは、ready
タグが与えられているものに正常性チェックが絞り込まれます。 - 活動性チェックの場合は
/health/live
。 活動性チェックでは、HealthCheckOptions.Predicate
でfalse
を返すことでStartupHostedServiceHealthCheck
が除外されます (詳細については、「正常性チェックをフィルター処理する」を参照してください)
次のコード例の内容:
- 対応性チェックでは、登録されているすべてのチェックが 'ready' タグと共に使用されます。
Predicate
では、すべてのチェックが除外され、200-Ok が返されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
サンプル アプリを使用して対応性/活動性構成シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario liveness
ブラウザーで、15 秒が経過するまで /health/ready
に数回アクセスします。 正常性チェックにより最初の 15 秒に対して Unhealthy
が報告されます。 15 秒後、エンドポイントから Healthy
が報告されます。これは、ホステッド サービスによる長時間実行タスクが完了したことを反映しています。
この例では、2 秒間の遅延で最初の対応性チェックを実行する正常性チェック パブリッシャー (IHealthCheckPublisher の実装) も作成されます。 詳細については、「正常性チェック パブリッシャー」セクションをご覧ください。
Kubernetes の例
対応性チェックと活動性チェックを使い分けることは、Kubernetes などの環境で便利です。 Kubernetes では、要求を受け入れる前に、基礎をなすデータベースの可用性テストなど、時間のかかるスタートアップ作業の実行がアプリに要求されることがあります。 別個のチェックを利用することで、アプリは機能しているがまだ準備ができていないか、あるいはアプリが起動に失敗したかをオーケストレーターは区別できます。 Kubernetes の対応性プローブと活動性プローブに関する詳細については、Kubernetes ドキュメントの「Configure Liveness and Readiness Probes」 (活動性プローブと対応性プローブを設定する) を参照してください。
次の例では、Kubernetes 対応性プローブの構成を確認できます。
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /health/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
カスタム応答ライターを含むメトリック ベースのプローブ
このサンプル アプリでは、カスタム応答ライターを含む、メモリ正常性チェックを確認できます。
与えられたしきい値を超えるメモリがアプリで使用された場合、MemoryHealthCheck
からは劣化状態が報告されます (このサンプル アプリでは 1 GB)。 HealthCheckResult にはアプリのガベージ コレクター (GC) 情報が含まれています (MemoryHealthCheck.cs
)。
public class MemoryHealthCheck : IHealthCheck
{
private readonly IOptionsMonitor<MemoryCheckOptions> _options;
public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
{
_options = options;
}
public string Name => "memory_check";
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var options = _options.Get(context.Registration.Name);
// Include GC information in the reported diagnostics.
var allocated = GC.GetTotalMemory(forceFullCollection: false);
var data = new Dictionary<string, object>()
{
{ "AllocatedBytes", allocated },
{ "Gen0Collections", GC.CollectionCount(0) },
{ "Gen1Collections", GC.CollectionCount(1) },
{ "Gen2Collections", GC.CollectionCount(2) },
};
var status = (allocated < options.Threshold) ?
HealthStatus.Healthy : context.Registration.FailureStatus;
return Task.FromResult(new HealthCheckResult(
status,
description: "Reports degraded status if allocated bytes " +
$">= {options.Threshold} bytes.",
exception: null,
data: data));
}
}
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 AddCheck に渡して正常性チェックを有効にする代わりに、MemoryHealthCheck
がサービスとして登録されます。 IHealthCheck が登録されたサービスはすべて、正常性チェック サービスとミドルウェアで利用できます。 正常性チェック サービスはシングルトン サービスとして登録することをお勧めします。
サンプル アプリの CustomWriterStartup.cs
内:
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。 WriteResponse
委任が ResponseWriter プロパティに与えられることで、正常性チェックの実行時に、カスタム JSON 応答が出力されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
}
WriteResponse
デリゲートによって、CompositeHealthCheckResult
が JSON オブジェクトに書式設定され、正常性チェック応答の JSON 出力が生成されます。 詳細については、「出力をカスタマイズする」セクションをご覧ください。
サンプル アプリを使用してカスタム応答ライターを含むメトリックベースのプローブを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario writer
Note
AspNetCore.Diagnostics.HealthChecks
には、ディスク ストレージや最大値活動性のチェックなど、メトリックベースの正常性チェック シナリオが含まれます。
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
ポート別のフィルター処理
MapHealthChecks
でポートを指定する URL パターンを使用して RequireHost
を呼び出し、指定されたポートに正常性チェック要求を制限します。 この方法は通常、サービスを監視するためのポートを公開する目的で、コンテナー環境で使用されます。
サンプル アプリによって、環境変数構成プロバイダーを使用してポートが設定されます。 ポートは launchSettings.json
ファイルに設定され、環境変数を介して構成プロバイダーに渡されます。 管理ポートで要求を待つようにサーバーを設定する必要もあります。
サンプル アプリを使用し、管理ポート設定を実演するには、Properties
フォルダーで launchSettings.json
ファイルを作成します。
サンプル アプリの次の Properties/launchSettings.json
ファイルは、サンプル アプリのプロジェクト ファイルに含まれていないため、手動で作成する必要があります。
{
"profiles": {
"SampleApp": {
"commandName": "Project",
"commandLineArgs": "",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
"ASPNETCORE_MANAGEMENTPORT": "5001"
},
"applicationUrl": "http://localhost:5000/"
}
}
}
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 Startup.Configure
で MapHealthChecks
を呼び出して、正常性チェック エンドポイントを作成します。
サンプル アプリでは、Startup.Configure
のエンドポイントで RequireHost
を呼び出すと、構成の管理ポートが指定されます。
endpoints.MapHealthChecks("/health")
.RequireHost($"*:{Configuration["ManagementPort"]}");
エンドポイントは、Startup.Configure
のサンプル アプリで作成されます。 次のコード例の内容:
- 対応性チェックでは、登録されているすべてのチェックが 'ready' タグと共に使用されます。
Predicate
では、すべてのチェックが除外され、200-Ok が返されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Note
管理ポートをコードに明示的に設定することで、サンプル アプリで launchSettings.json
ファイルを作成することを回避できます。 HostBuilder が作成される Program.cs
で、ListenAnyIP の呼び出しを追加し、アプリの管理ポート エンドポイントを用意します。 ManagementPortStartup.cs
の Configure
で、RequireHost
を使用して管理ポートを指定します。
Program.cs
:
return new HostBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5001);
})
.UseStartup(startupType);
})
.Build();
ManagementPortStartup.cs
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});
サンプル アプリを使用して管理ポート構成シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario port
正常性チェック ライブラリを配布する
正常性チェックをライブラリとして配布するには:
スタンドアロン クラスとして IHealthCheck インターフェイスを実装する正常性チェックを記述します。 このクラスは、設定データにアクセスする目的で依存関係挿入 (DI)、型のアクティブ化、名前付きオプションに依存できます。
CheckHealthAsync
の正常性チェックのロジックでは、次のようになります。data1
とdata2
は、プローブの正常性チェック ロジックを実行するためにメソッドで使用されます。AccessViolationException
が処理されます。
AccessViolationException が発生すると、HealthCheckResult とともに FailureStatus が返され、ユーザーは正常性チェックの失敗状態を構成できます。
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace SampleApp { public class ExampleHealthCheck : IHealthCheck { private readonly string _data1; private readonly int? _data2; public ExampleHealthCheck(string data1, int? data2) { _data1 = data1 ?? throw new ArgumentNullException(nameof(data1)); _data2 = data2 ?? throw new ArgumentNullException(nameof(data2)); } public async Task<HealthCheckResult> CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken) { try { return HealthCheckResult.Healthy(); } catch (AccessViolationException ex) { return new HealthCheckResult( context.Registration.FailureStatus, description: "An access violation occurred during the check.", exception: ex, data: null); } } } }
拡張メソッドを記述します。拡張メソッドを使用するアプリがその
Startup.Configure
メソッドで呼び出すパラメーターを指定します。 次の例では、次の正常性チェック メソッド シグネチャを想定します。ExampleHealthCheck(string, string, int )
先のシグネチャは、正常性チェック プローブ ロジックを処理する目的で
ExampleHealthCheck
に追加データが要求されることを示しています。 正常性チェックが拡張メソッドに登録されたときに正常性チェック インスタンスを作成するための委任にデータが提供されます。 次の例では、呼び出し元によって次が任意で指定されます。- 正常性チェック名 (
name
)。null
の場合、example_health_check
が使用されます。 - 正常性チェックの文字列データ ポイント (
data1
)。 - 正常性チェックの整数データ ポイント (
data2
)。null
の場合、1
が使用されます。 - エラー状態 (HealthStatus)。 既定値は、
null
です。null
の場合、エラー状態に対して HealthStatus.Unhealthy が報告されます。 - タグ (
IEnumerable<string>
)。
using System.Collections.Generic; using Microsoft.Extensions.Diagnostics.HealthChecks; public static class ExampleHealthCheckBuilderExtensions { const string DefaultName = "example_health_check"; public static IHealthChecksBuilder AddExampleHealthCheck( this IHealthChecksBuilder builder, string name = default, string data1, int data2 = 1, HealthStatus? failureStatus = default, IEnumerable<string> tags = default) { return builder.Add(new HealthCheckRegistration( name ?? DefaultName, sp => new ExampleHealthCheck(data1, data2), failureStatus, tags)); } }
- 正常性チェック名 (
正常性チェック パブリッシャー
サービス コンテナーに IHealthCheckPublisher が追加されると、正常性チェック システムにより定期的に正常性チェックが実行され、結果と共に PublishAsync
が呼び出されます。 これは、正常性を判断する目的で監視システムを定期的に呼び出すことを各プロセスに求めるプッシュベースの監視システム シナリオで便利です。
IHealthCheckPublisher インターフェイスには単一メソッドが与えられます。
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions を使うと次を設定できます。
- Delay:アプリが起動した後、IHealthCheckPublisher インスタンスを実行する前に適用される初期遅延です。 遅延はスタートアップ時に一度だけ適用され、以降の繰り返しには適用されません。 既定値は 5 秒です。
- Period:IHealthCheckPublisher を実行する期間です。 既定値は 30 秒です。
- Predicate:Predicate が
null
(既定値) の場合、正常性チェック パブリッシャー サービスにより登録済みのすべての正常性チェックが実行されます。 正常性チェックのサブセットを実行するには、チェックのセットをフィルター処理する関数を指定します。 述語は期間ごとに評価されます。 - Timeout:すべての IHealthCheckPublisher インスタンスに対する正常性チェックの実行のタイムアウトです。 タイムアウトなしで実行するには InfiniteTimeSpan を使います。 既定値は 30 秒です。
サンプル アプリでは、ReadinessPublisher
が IHealthCheckPublisher の実装です。 正常性チェックの状態は、チェックごとに以下のログ レベルでログに記録されます。
- 情報 (LogInformation): 正常性チェックの状態が Healthy の場合。
- エラー (LogError) 状態が Degraded または Unhealthy の場合。
public class ReadinessPublisher : IHealthCheckPublisher
{
private readonly ILogger _logger;
public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
{
_logger = logger;
}
// The following example is for demonstration purposes only. Health Checks
// Middleware already logs health checks results. A real-world readiness
// check in a production app might perform a set of more expensive or
// time-consuming checks to determine if other resources are responding
// properly.
public Task PublishAsync(HealthReport report,
CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
_logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
else
{
_logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
cancellationToken.ThrowIfCancellationRequested();
return Task.CompletedTask;
}
}
サンプル アプリの LivenessProbeStartup
の例では、対応性チェック StartupHostedService
にはスタートアップの遅延が 2 秒間あり、30 秒ごとにチェックが実行されます。 IHealthCheckPublisher の実装をアクティブ化するために、サンプルでは ReadinessPublisher
をシングルトン サービスとして依存関係の挿入 (DI) コンテナーに登録しています。
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>();
Note
AspNetCore.Diagnostics.HealthChecks
には、Application Insights など、いくつかのシステムのパブリッシャーが含まれます。
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
MapWhen で正常性チェックを制限する
MapWhen を使用して、正常性チェック エンドポイントの要求パイプラインを条件付きで分岐します。
次の例では、api/HealthCheck
エンドポイントに対して GET 要求が受信された場合に、MapWhen
が要求パイプラインを分岐して正常性チェック ミドルウェアをアクティブ化します。
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
詳細については、「ASP.NET Core のミドルウェア」を参照してください。
ASP.NET Core からは、アプリ インフラストラクチャ コンポーネントの正常性を報告するための正常性チェック ミドルウェアとライブラリが提供されます。
正常性チェックは HTTP エンドポイントとしてアプリによって公開されます。 正常性チェック エンドポイントは、さまざまなリアルタイム監視シナリオに合わせて設定できます。
- 正常性プローブは、アプリの状態を確認する目的でコンテナー オーケストレーターとロード バランサーによって使用できます。 たとえば、正常性チェックで問題が確認された場合、コンテナー オーケストレーターは実行中の展開を停止したり、コンテナーを再起動したりします。 ロード バランサーはアプリの異常に対処するため、問題のあるインスタンスから正常なインスタンスにトラフィック経路を変更することがあります。
- メモリ、ディスク、その他の物理サーバー リソースの使用を監視し、正常性の状態を確認できます。
- 正常性チェックでは、データベースや外部サービス エンドポイントなど、アプリの依存関係をテストし、それらが利用できることと正常に機能していることを確認できます。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
サンプル アプリには、この記事で説明されているシナリオの例が含まれています。 所与のシナリオに対してサンプル アプリを実行するには、コマンド シェルでプロジェクトのフォルダーから dotnet run コマンドを使用します。 サンプル アプリの詳しい使用方法については、サンプル アプリの README.md
ファイルとこの記事のシナリオ説明を参照してください。
前提条件
正常性チェックは通常、アプリの状態を確認する目的で、外部の監視サービスまたはコンテナー オーケストレーターと共に使用されます。 正常性チェックをアプリに追加する前に、使用する監視システムを決定します。 監視システムからは、作成する正常性チェックの種類とそのエンドポイントの設定方法が指示されます。
Microsoft.AspNetCore.Diagnostics.HealthChecks
パッケージは、ASP.NET Core アプリに対して暗黙的に参照されます。 Entity Framework Core を使用して正常性チェックを実行するには、Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
パッケージへのパッケージ参照を追加します。
サンプル アプリからは、いくつかのシナリオで正常性チェックを実演するスタートアップ コードが提供されます。 データベース プローブ シナリオでは、AspNetCore.Diagnostics.HealthChecks
を使用して、データベース接続の正常性をチェックします。 DbContext プローブ シナリオでは、EF CoreDbContext
を使用して、データベースがチェックされます。 データベース シナリオを探索するために、サンプル アプリでは次のことが行われます:
- データベースを作成して、
appsettings.json
ファイルにその接続文字列を指定します。 - そのプロジェクト ファイルに次のパッケージ参照が含まれています:
Note
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
もう 1 つの正常性チェックのシナリオでは、1 つの管理ポートに正常性チェックを絞り込む方法が実演されます。 このサンプル アプリでは、管理 URL と管理ポートを含む Properties/launchSettings.json
ファイルを作成する必要があります。 詳細については、「ポート別のフィルター処理」セクションを参照してください。
基本的な正常性プローブ
多くのアプリでは、アプリが要求を処理できること (活動性) を報告する基本的な正常性チェック構成で十分にアプリの状態を検出できます。
基本の構成では、正常性チェック サービスを登録し、正常性チェック ミドルウェアを呼び出します。このミドルウェアが特定の URL エンドポイントにおける正常性を返します。 既定では、特定の依存関係またはサブシステムをテストする正常性チェックは登録されていません。 正常性エンドポイント URL で応答できる場合、そのアプリは正常であると見なされます。 既定の応答ライターによって、プレーンテキストの応答として状態 (HealthStatus) がクライアントに書き込まれます。このとき、状態として HealthStatus.Healthy、HealthStatus.Degraded、または HealthStatus.Unhealthy が示されます。
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 Startup.Configure
で MapHealthChecks
を呼び出して、正常性チェック エンドポイントを作成します。
サンプル アプリでは、正常性チェック エンドポイントは /health
で作成されます (BasicStartup.cs
)。
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
サンプル アプリを使用して基本的な構成シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario basic
Docker の例
Docker からは、組み込み HEALTHCHECK
ディレクティブが提供されます。これを使用し、基本的な正常性チェック構成を使用するアプリの状態を確認できます。
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
正常性チェックを作成する
正常性チェックは IHealthCheck インターフェイスを実装することで作成されます。 CheckHealthAsync メソッドによって、Healthy
、Degraded
、Unhealthy
のいずれかの正常性を示す HealthCheckResult が返されます。 この結果が構成可能な状態コードと共にプレーンテキストの応答として書き込まれます (構成の説明は「正常性チェック オプション」セクションにあります)。 HealthCheckResult からは、任意のキーと値のペアを返すこともできます。
次の ExampleHealthCheck
クラスからは、正常性チェックのレイアウトがどのようなものかがわかります。 正常性チェックのロジックが CheckHealthAsync
メソッドに配置されています。 次の例では、ダミー変数 healthCheckResultHealthy
が true
に設定されます。 healthCheckResultHealthy
の値が false
に設定されている場合、HealthCheckResult.Unhealthy
状態が返されます。
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("An unhealthy result."));
}
}
正常性チェック サービスを登録する
Startup.ConfigureServices
の AddCheck によって ExampleHealthCheck
型が正常性チェック サービスに追加されます。
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
次の例にある AddCheck オーバーロードでは、正常性チェックでエラーが報告されると、レポートにエラー状態 (HealthStatus) が設定されます。 エラー状態が null
(既定) に設定された場合、HealthStatus.Unhealthy が報告されます。 このオーバーロードはライブラリ作成者にとって便利です。この設定に正常性チェック実装が従う場合、正常性チェック エラーが発生したとき、ライブラリによって指示されるエラー状態がアプリによって適用されます。
タグを使用し、正常性チェックをフィルター処理できます (詳細は「正常性チェックをフィルター処理する」セクションにあります)。
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck では、lambda 関数も実行できます。 次の例では、正常性チェック名に「Example
」が指定されいます。このチェックでは状態として常に正常が返されます。
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
AddTypeActivatedCheck を呼び出して、正常性チェックの実装に引数を渡します。 次の例では、TestHealthCheckWithArgs
は CheckHealthAsync の呼び出し時に使用する整数と文字列を受け入れます。
private class TestHealthCheckWithArgs : IHealthCheck
{
public TestHealthCheckWithArgs(int i, string s)
{
I = i;
S = s;
}
public int I { get; set; }
public string S { get; set; }
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
CancellationToken cancellationToken = default)
{
...
}
}
TestHealthCheckWithArgs
は実装に渡された整数と文字列を使用して AddTypeActivatedCheck
を呼び出すことによって登録されます。
services.AddHealthChecks()
.AddTypeActivatedCheck<TestHealthCheckWithArgs>(
"test",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" },
args: new object[] { 5, "string" });
正常性チェックのルーティングを使用する
Startup.Configure
で、エンドポイントの URL または相対パスを使用して、エンドポイント ビルダーで MapHealthChecks
を呼び出します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
ホストが必要
RequireHost
を呼び出して、正常性チェック エンドポイントに許可されている 1 つ以上のホストを指定します。 ホストは、punycode ではなく Unicode にする必要があります。また、ポートを含めることができます。 コレクションが指定されていない場合は、任意のホストを使用できます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});
詳細については、「ポート別のフィルター処理」セクションを参照してください。
承認が必要
RequireAuthorization
を呼び出して、正常性チェック要求エンドポイントで承認ミドルウェアを実行します。 RequireAuthorization
のオーバーロードには 1 つ以上の承認ポリシーを使用できます。 ポリシーが指定されていない場合は、既定の承認ポリシーが使用されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireAuthorization();
});
クロスオリジン要求 (CORS) の有効化
ブラウザーから手動で正常性チェックを実行することは一般的な使用シナリオではありませんが、正常性チェック エンドポイントで RequireCors
を呼び出して CORS ミドルウェアを有効にすることができます。 RequireCors
のオーバーロードには、CORS ポリシー ビルダーのデリゲート (CorsPolicyBuilder
) またはポリシー名を使用できます。 ポリシーが指定されていない場合は、既定の CORS ポリシーが使用されます。 詳細については、「ASP.NET Core でクロスオリジン要求 (CORS) を有効にする」を参照してください。
正常性チェック オプション
HealthCheckOptions では、正常性チェックの動作をカスタマイズできます。
正常性チェックをフィルター処理する
既定では、正常性チェック ミドルウェアでは、登録されている正常性チェックがすべて実行されます。 正常性チェックのサブセットを実行するには、Predicate オプションにブール値を返す関数を指定します。 次の例では、関数の条件文にあるそのタグ (bar_tag
) により Bar
正常性チェックが除外されます。true
は、正常性チェックの Tags プロパティが foo_tag
か baz_tag
に一致した場合にのみ返されます。
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
によって 'Bar' 正常性チェックが除外されます。 Foo と Baz のみが実行されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
});
HTTP 状態コードをカスタマイズする
ResultStatusCodes を使用し、HTTP 状態コードに対する正常性状態のマッピングをカスタマイズします。 次の StatusCodes 代入はミドルウェアによって使用される既定値です。 要件に合わせて状態コード値を変更します。
Startup.Configure
の場合:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
});
キャッシュ ヘッダーを非表示にする
AllowCachingResponses によって、応答キャッシュを禁止する目的で、正常性チェック ミドルウェアによって HTTP ヘッダーがプローブ応答に追加されるかどうかが制御されます。 値が false
(既定) の場合、応答キャッシュを禁止する目的で、ミドルウェアによってヘッダー Cache-Control
、Expires
、Pragma
が設定またはオーバーライドされます。 値が true
の場合、応答のキャッシュ ヘッダーがミドルウェアによって変更されることはありません。
Startup.Configure
の場合:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = true
});
});
出力をカスタマイズする
Startup.Configure
で、HealthCheckOptions.ResponseWriter オプションを、応答を書き込むためのデリゲートに設定します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
});
既定の委任では、文字列値 HealthReport.Status
を含む、最小のプレーンテキスト応答が書き込まれます。 次のカスタム デリゲートでは、カスタム JSON 応答が出力されます。
サンプル アプリの最初の例は、System.Text.Json の使用方法を示しています。
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions
{
Indented = true
};
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartObject();
writer.WriteString("status", result.Status.ToString());
writer.WriteStartObject("results");
foreach (var entry in result.Entries)
{
writer.WriteStartObject(entry.Key);
writer.WriteString("status", entry.Value.Status.ToString());
writer.WriteString("description", entry.Value.Description);
writer.WriteStartObject("data");
foreach (var item in entry.Value.Data)
{
writer.WritePropertyName(item.Key);
JsonSerializer.Serialize(
writer, item.Value, item.Value?.GetType() ??
typeof(object));
}
writer.WriteEndObject();
writer.WriteEndObject();
}
writer.WriteEndObject();
writer.WriteEndObject();
}
var json = Encoding.UTF8.GetString(stream.ToArray());
return context.Response.WriteAsync(json);
}
}
2 番目の例は、Newtonsoft.Json の使用方法を示しています。
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json";
var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
return context.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
サンプル アプリでは、CustomWriterStartup.cs
の SYSTEM_TEXT_JSON
プリプロセッサ ディレクティブをコメント アウトして、Newtonsoft.Json
バージョンの WriteResponse
を有効にします。
正常性チェック API には、複雑な JSON の戻り値の形式に対する組み込みのサポートが用意されていません。この形式は、選択した監視システムに固有のものであるためです。 必要に応じて、上記の例の応答をカスタマイズします。 System.Text.Json
を使用した JSON シリアル化の詳細については、.NET で JSON をシリアル化および逆シリアル化する方法に関する記事をご覧ください。
データベース プローブ
正常性チェックでは、データベースが通常どおり応答しているかどうかを示すブール値テストとして実行されるよう、データベース クエリを指定できます。
このサンプル アプリでは、ASP.NET Core アプリ用の正常性チェック ライブラリ AspNetCore.Diagnostics.HealthChecks
を使用して、SQL Server データベースの正常性チェックを実行します。 AspNetCore.Diagnostics.HealthChecks
によってデータベースに対して SELECT 1
クエリが実行され、データベースへの接続が正常であることが確認されます。
警告
クエリでデータベース接続を確認するとき、すぐに返されるクエリを選択します。 このクエリ手法には、データベースをオーバーロードし、そのパフォーマンスを低下させるというリスクがあります。 ほとんどの場合、テスト クエリは実行する必要がありません。 データベースに正常に接続できれば十分です。 クエリを実行する必要があれば、SELECT 1
など、単純な SELECT クエリを選択してください。
AspNetCore.HealthChecks.SqlServer
へのパッケージ参照を含めます。
サンプル アプリの appsettings.json
ファイルに有効なデータベース接続文字列を指定します。 このアプリでは HealthCheckSample
という名前の SQL Server データベースが使用されます。
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"IncludeScopes": "true"
}
},
"AllowedHosts": "*"
}
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 サンプル アプリでは、データベースの接続文字列 (DbHealthStartup.cs
) を利用して AddSqlServer
メソッドを呼び出します。
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
サンプル アプリを使用してデータベース プローブ シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario db
Note
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
Entity Framework Core DbContext プローブ
DbContext
チェックでは、EF CoreDbContext
に対して構成されているデータベースとアプリとが通信できることが確認されます。 DbContext
チェックは、次のようなアプリでサポートされています。
- Entity Framework (EF) Core を使用する。
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
へのパッケージ参照を含めます。
AddDbContextCheck<TContext>
によって DbContext
の正常性チェックが登録されます。 DbContext
は TContext
としてメソッドに指定されます。 オーバーロードはエラー状態、タグ、カスタム テスト クエリの設定に利用できます。
既定では:
DbContextHealthCheck
は、EF Core のCanConnectAsync
メソッドを呼び出します。AddDbContextCheck
メソッドのオーバーロードを使用して正常性を確認するときに実行される操作をカスタマイズできます。- 正常性チェックの名前は
TContext
型の名前になります。
サンプル アプリでは、AppDbContext
が AddDbContextCheck
に提供され、Startup.ConfigureServices
でサービスとして登録されます (DbContextHealthStartup.cs
)。
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
}
サンプル アプリを利用して DbContext
プローブ シナリオを実行するには、接続文字列によって指定されるデータベースが SQL Server インスタンスに存在しないことを確認します。 データベースが存在する場合、それを削除します。
コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario dbcontext
アプリの実行後、ブラウザーで /health
エンドポイントに要求することで正常性状態を確認します。 データベースと AppDbContext
は存在しません。そこで、アプリによって次の応答が返されます。
Unhealthy
サンプル アプリにデータベースを作成させます。 /createdatabase
に要求を行います。 アプリからの応答は次のようになります。
Creating the database...
Done!
Navigate to /health to see the health status.
/health
エンドポイントに要求を行います。 データベースとコンテキストが存在します。そのため、アプリによって次の応答が返されます。
Healthy
サンプル アプリにデータベースを削除させます。 /deletedatabase
に要求を行います。 アプリからの応答は次のようになります。
Deleting the database...
Done!
Navigate to /health to see the health status.
/health
エンドポイントに要求を行います。 アプリから異常という応答が返されます。
Unhealthy
対応性と活動性に区分されるプローブ
一部のホスティング シナリオでは、2 つのアプリ状態を区別する一組の正常性チェックが使用されます。
- "対応性" は、アプリが通常どおり実行されているが、要求を受け取る準備ができていないのか、あるいはそうではないのかを示します。
- "活動性" は、アプリがクラッシュしたため、再起動する必要があるのかどうかを示します。
次に例を示します。アプリでは、大きな構成ファイルをダウンロードしないと、要求を処理する準備ができません。 初回ダウンロードに失敗した場合、アプリを再起動することは望みません。アプリはファイルのダウンロードを数回再試行する可能性があるためです。 liveness probe を使用し、プロセスの活動性を記述します。他のチェックは実行されません。 また、構成ファイルのダウンロードが完了する前は、要求がアプリに送信されないようにします。 "対応性プローブ" を使用し、ダウンロードが成功し、要求を受け取る準備がアプリにできるまで、"準備できていない" 状態を示します。
サンプル アプリには、ホステッド サービスの長時間実行スタートアップ タスクの完了を報告する正常性チェックが含まれています。 StartupHostedServiceHealthCheck
によって StartupTaskCompleted
というプロパティが公開されます。ホステッド サービスでは長時間実行タスクの完了時にこのプロパティを true
に設定できます (StartupHostedServiceHealthCheck.cs
)。
public class StartupHostedServiceHealthCheck : IHealthCheck
{
private volatile bool _startupTaskCompleted = false;
public string Name => "slow_dependency_check";
public bool StartupTaskCompleted
{
get => _startupTaskCompleted;
set => _startupTaskCompleted = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
if (StartupTaskCompleted)
{
return Task.FromResult(
HealthCheckResult.Healthy("The startup task is finished."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("The startup task is still running."));
}
}
長時間実行バックグラウンド タスクはホステッド サービスによって開始されます (Services/StartupHostedService
)。 タスクが終わると、StartupHostedServiceHealthCheck.StartupTaskCompleted
が true
に設定されます。
public class StartupHostedService : IHostedService, IDisposable
{
private readonly int _delaySeconds = 15;
private readonly ILogger _logger;
private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;
public StartupHostedService(ILogger<StartupHostedService> logger,
StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
{
_logger = logger;
_startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is starting.");
// Simulate the effect of a long-running startup task.
Task.Run(async () =>
{
await Task.Delay(_delaySeconds * 1000);
_startupHostedServiceHealthCheck.StartupTaskCompleted = true;
_logger.LogInformation("Startup Background Service has started.");
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is stopping.");
return Task.CompletedTask;
}
public void Dispose()
{
}
}
ホステッド サービスと共に Startup.ConfigureServices
で正常性チェックが AddCheck に登録されます。 ホステッド サービスでは正常性チェックにプロパティを設定する必要があるため、正常性チェックはサービス コンテナーにも登録されます (LivenessProbeStartup.cs
)。
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();
services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});
services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。 サンプル アプリでは、正常性チェック エンドポイントは次の場所に作成されます。
- 対応性チェックの場合は
/health/ready
。 対応性チェックでは、ready
タグが与えられているものに正常性チェックが絞り込まれます。 - 活動性チェックの場合は
/health/live
。 活動性チェックでは、HealthCheckOptions.Predicate
でfalse
を返すことでStartupHostedServiceHealthCheck
が除外されます (詳細については、「正常性チェックをフィルター処理する」を参照してください)
次のコード例の内容:
- 対応性チェックでは、登録されているすべてのチェックが 'ready' タグと共に使用されます。
Predicate
では、すべてのチェックが除外され、200-Ok が返されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
サンプル アプリを使用して対応性/活動性構成シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario liveness
ブラウザーで、15 秒が経過するまで /health/ready
に数回アクセスします。 正常性チェックにより最初の 15 秒に対して Unhealthy
が報告されます。 15 秒後、エンドポイントから Healthy
が報告されます。これは、ホステッド サービスによる長時間実行タスクが完了したことを反映しています。
この例では、2 秒間の遅延で最初の対応性チェックを実行する正常性チェック パブリッシャー (IHealthCheckPublisher の実装) も作成されます。 詳細については、「正常性チェック パブリッシャー」セクションをご覧ください。
Kubernetes の例
対応性チェックと活動性チェックを使い分けることは、Kubernetes などの環境で便利です。 Kubernetes では、要求を受け入れる前に、基礎をなすデータベースの可用性テストなど、時間のかかるスタートアップ作業の実行がアプリに要求されることがあります。 別個のチェックを利用することで、アプリは機能しているがまだ準備ができていないか、あるいはアプリが起動に失敗したかをオーケストレーターは区別できます。 Kubernetes の対応性プローブと活動性プローブに関する詳細については、Kubernetes ドキュメントの「Configure Liveness and Readiness Probes」 (活動性プローブと対応性プローブを設定する) を参照してください。
次の例では、Kubernetes 対応性プローブの構成を確認できます。
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /health/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
カスタム応答ライターを含むメトリック ベースのプローブ
このサンプル アプリでは、カスタム応答ライターを含む、メモリ正常性チェックを確認できます。
与えられたしきい値を超えるメモリがアプリで使用された場合、MemoryHealthCheck
からは劣化状態が報告されます (このサンプル アプリでは 1 GB)。 HealthCheckResult にはアプリのガベージ コレクター (GC) 情報が含まれています (MemoryHealthCheck.cs
)。
public class MemoryHealthCheck : IHealthCheck
{
private readonly IOptionsMonitor<MemoryCheckOptions> _options;
public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
{
_options = options;
}
public string Name => "memory_check";
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var options = _options.Get(context.Registration.Name);
// Include GC information in the reported diagnostics.
var allocated = GC.GetTotalMemory(forceFullCollection: false);
var data = new Dictionary<string, object>()
{
{ "AllocatedBytes", allocated },
{ "Gen0Collections", GC.CollectionCount(0) },
{ "Gen1Collections", GC.CollectionCount(1) },
{ "Gen2Collections", GC.CollectionCount(2) },
};
var status = (allocated < options.Threshold) ?
HealthStatus.Healthy : context.Registration.FailureStatus;
return Task.FromResult(new HealthCheckResult(
status,
description: "Reports degraded status if allocated bytes " +
$">= {options.Threshold} bytes.",
exception: null,
data: data));
}
}
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 AddCheck に渡して正常性チェックを有効にする代わりに、MemoryHealthCheck
がサービスとして登録されます。 IHealthCheck が登録されたサービスはすべて、正常性チェック サービスとミドルウェアで利用できます。 正常性チェック サービスはシングルトン サービスとして登録することをお勧めします。
サンプル アプリの CustomWriterStartup.cs
内:
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
正常性チェック エンドポイントを作成するには、Startup.Configure
で MapHealthChecks
を呼び出します。 WriteResponse
委任が ResponseWriter プロパティに与えられることで、正常性チェックの実行時に、カスタム JSON 応答が出力されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
}
WriteResponse
デリゲートによって、CompositeHealthCheckResult
が JSON オブジェクトに書式設定され、正常性チェック応答の JSON 出力が生成されます。 詳細については、「出力をカスタマイズする」セクションをご覧ください。
サンプル アプリを使用してカスタム応答ライターを含むメトリックベースのプローブを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario writer
Note
AspNetCore.Diagnostics.HealthChecks
には、ディスク ストレージや最大値活動性のチェックなど、メトリックベースの正常性チェック シナリオが含まれます。
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
ポート別のフィルター処理
MapHealthChecks
でポートを指定する URL パターンを使用して RequireHost
を呼び出し、指定されたポートに正常性チェック要求を制限します。 この方法は通常、サービスを監視するためのポートを公開する目的で、コンテナー環境で使用されます。
サンプル アプリによって、環境変数構成プロバイダーを使用してポートが設定されます。 ポートは launchSettings.json
ファイルに設定され、環境変数を介して構成プロバイダーに渡されます。 管理ポートで要求を待つようにサーバーを設定する必要もあります。
サンプル アプリを使用し、管理ポート設定を実演するには、Properties
フォルダーで launchSettings.json
ファイルを作成します。
サンプル アプリの次の Properties/launchSettings.json
ファイルは、サンプル アプリのプロジェクト ファイルに含まれていないため、手動で作成する必要があります。
{
"profiles": {
"SampleApp": {
"commandName": "Project",
"commandLineArgs": "",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
"ASPNETCORE_MANAGEMENTPORT": "5001"
},
"applicationUrl": "http://localhost:5000/"
}
}
}
正常性チェック サービスを Startup.ConfigureServices
の AddHealthChecks に登録します。 Startup.Configure
で MapHealthChecks
を呼び出して、正常性チェック エンドポイントを作成します。
サンプル アプリでは、Startup.Configure
のエンドポイントで RequireHost
を呼び出すと、構成の管理ポートが指定されます。
endpoints.MapHealthChecks("/health")
.RequireHost($"*:{Configuration["ManagementPort"]}");
エンドポイントは、Startup.Configure
のサンプル アプリで作成されます。 次のコード例の内容:
- 対応性チェックでは、登録されているすべてのチェックが 'ready' タグと共に使用されます。
Predicate
では、すべてのチェックが除外され、200-Ok が返されます。
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});
endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
}
Note
管理ポートをコードに明示的に設定することで、サンプル アプリで launchSettings.json
ファイルを作成することを回避できます。 HostBuilder が作成される Program.cs
で、ListenAnyIP の呼び出しを追加し、アプリの管理ポート エンドポイントを用意します。 ManagementPortStartup.cs
の Configure
で、RequireHost
を使用して管理ポートを指定します。
Program.cs
:
return new HostBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel()
.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5001);
})
.UseStartup(startupType);
})
.Build();
ManagementPortStartup.cs
:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});
サンプル アプリを使用して管理ポート構成シナリオを実行するには、コマンド シェルでプロジェクトのフォルダーから次のコマンドを実行します。
dotnet run --scenario port
正常性チェック ライブラリを配布する
正常性チェックをライブラリとして配布するには:
スタンドアロン クラスとして IHealthCheck インターフェイスを実装する正常性チェックを記述します。 このクラスは、設定データにアクセスする目的で依存関係挿入 (DI)、型のアクティブ化、名前付きオプションに依存できます。
CheckHealthAsync
の正常性チェックのロジックでは、次のようになります。data1
とdata2
は、プローブの正常性チェック ロジックを実行するためにメソッドで使用されます。AccessViolationException
が処理されます。
AccessViolationException が発生すると、HealthCheckResult とともに FailureStatus が返され、ユーザーは正常性チェックの失敗状態を構成できます。
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace SampleApp { public class ExampleHealthCheck : IHealthCheck { private readonly string _data1; private readonly int? _data2; public ExampleHealthCheck(string data1, int? data2) { _data1 = data1 ?? throw new ArgumentNullException(nameof(data1)); _data2 = data2 ?? throw new ArgumentNullException(nameof(data2)); } public async Task<HealthCheckResult> CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken) { try { return HealthCheckResult.Healthy(); } catch (AccessViolationException ex) { return new HealthCheckResult( context.Registration.FailureStatus, description: "An access violation occurred during the check.", exception: ex, data: null); } } } }
拡張メソッドを記述します。拡張メソッドを使用するアプリがその
Startup.Configure
メソッドで呼び出すパラメーターを指定します。 次の例では、次の正常性チェック メソッド シグネチャを想定します。ExampleHealthCheck(string, string, int )
先のシグネチャは、正常性チェック プローブ ロジックを処理する目的で
ExampleHealthCheck
に追加データが要求されることを示しています。 正常性チェックが拡張メソッドに登録されたときに正常性チェック インスタンスを作成するための委任にデータが提供されます。 次の例では、呼び出し元によって次が任意で指定されます。- 正常性チェック名 (
name
)。null
の場合、example_health_check
が使用されます。 - 正常性チェックの文字列データ ポイント (
data1
)。 - 正常性チェックの整数データ ポイント (
data2
)。null
の場合、1
が使用されます。 - エラー状態 (HealthStatus)。 既定値は、
null
です。null
の場合、エラー状態に対して HealthStatus.Unhealthy が報告されます。 - タグ (
IEnumerable<string>
)。
using System.Collections.Generic; using Microsoft.Extensions.Diagnostics.HealthChecks; public static class ExampleHealthCheckBuilderExtensions { const string DefaultName = "example_health_check"; public static IHealthChecksBuilder AddExampleHealthCheck( this IHealthChecksBuilder builder, string name = default, string data1, int data2 = 1, HealthStatus? failureStatus = default, IEnumerable<string> tags = default) { return builder.Add(new HealthCheckRegistration( name ?? DefaultName, sp => new ExampleHealthCheck(data1, data2), failureStatus, tags)); } }
- 正常性チェック名 (
正常性チェック パブリッシャー
サービス コンテナーに IHealthCheckPublisher が追加されると、正常性チェック システムにより定期的に正常性チェックが実行され、結果と共に PublishAsync
が呼び出されます。 これは、正常性を判断する目的で監視システムを定期的に呼び出すことを各プロセスに求めるプッシュベースの監視システム シナリオで便利です。
IHealthCheckPublisher インターフェイスには単一メソッドが与えられます。
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions を使うと次を設定できます。
- Delay:アプリが起動した後、IHealthCheckPublisher インスタンスを実行する前に適用される初期遅延です。 遅延はスタートアップ時に一度だけ適用され、以降の繰り返しには適用されません。 既定値は 5 秒です。
- Period:IHealthCheckPublisher を実行する期間です。 既定値は 30 秒です。
- Predicate:Predicate が
null
(既定値) の場合、正常性チェック パブリッシャー サービスにより登録済みのすべての正常性チェックが実行されます。 正常性チェックのサブセットを実行するには、チェックのセットをフィルター処理する関数を指定します。 述語は期間ごとに評価されます。 - Timeout:すべての IHealthCheckPublisher インスタンスに対する正常性チェックの実行のタイムアウトです。 タイムアウトなしで実行するには InfiniteTimeSpan を使います。 既定値は 30 秒です。
サンプル アプリでは、ReadinessPublisher
が IHealthCheckPublisher の実装です。 正常性チェックの状態は、チェックごとに以下のログ レベルでログに記録されます。
- 情報 (LogInformation): 正常性チェックの状態が Healthy の場合。
- エラー (LogError) 状態が Degraded または Unhealthy の場合。
public class ReadinessPublisher : IHealthCheckPublisher
{
private readonly ILogger _logger;
public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
{
_logger = logger;
}
// The following example is for demonstration purposes only. Health Checks
// Middleware already logs health checks results. A real-world readiness
// check in a production app might perform a set of more expensive or
// time-consuming checks to determine if other resources are responding
// properly.
public Task PublishAsync(HealthReport report,
CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
_logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
else
{
_logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
cancellationToken.ThrowIfCancellationRequested();
return Task.CompletedTask;
}
}
サンプル アプリの LivenessProbeStartup
の例では、対応性チェック StartupHostedService
にはスタートアップの遅延が 2 秒間あり、30 秒ごとにチェックが実行されます。 IHealthCheckPublisher の実装をアクティブ化するために、サンプルでは ReadinessPublisher
をシングルトン サービスとして依存関係の挿入 (DI) コンテナーに登録しています。
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>();
Note
AspNetCore.Diagnostics.HealthChecks
には、Application Insights など、いくつかのシステムのパブリッシャーが含まれます。
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
MapWhen で正常性チェックを制限する
MapWhen を使用して、正常性チェック エンドポイントの要求パイプラインを条件付きで分岐します。
次の例では、api/HealthCheck
エンドポイントに対して GET 要求が受信された場合に、MapWhen
が要求パイプラインを分岐して正常性チェック ミドルウェアをアクティブ化します。
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
詳細については、「ASP.NET Core のミドルウェア」を参照してください。
ASP.NET Core からは、アプリ インフラストラクチャ コンポーネントの正常性を報告するための正常性チェック ミドルウェアとライブラリが提供されます。
正常性チェックは HTTP エンドポイントとしてアプリによって公開されます。 正常性チェック エンドポイントは、さまざまなリアルタイム監視シナリオに合わせて設定できます。
- 正常性プローブは、アプリの状態を確認する目的でコンテナー オーケストレーターとロード バランサーによって使用できます。 たとえば、正常性チェックで問題が確認された場合、コンテナー オーケストレーターは実行中の展開を停止したり、コンテナーを再起動したりします。 ロード バランサーはアプリの異常に対処するため、問題のあるインスタンスから正常なインスタンスにトラフィック経路を変更することがあります。
- メモリ、ディスク、その他の物理サーバー リソースの使用を監視し、正常性の状態を確認できます。
- 正常性チェックでは、データベースや外部サービス エンドポイントなど、アプリの依存関係をテストし、それらが利用できることと正常に機能していることを確認できます。
正常性チェックは通常、アプリの状態を確認する目的で、外部の監視サービスまたはコンテナー オーケストレーターと共に使用されます。 正常性チェックをアプリに追加する前に、使用する監視システムを決定します。 監視システムからは、作成する正常性チェックの種類とそのエンドポイントの設定方法が指示されます。
基本的な正常性プローブ
多くのアプリでは、アプリが要求を処理できること (活動性) を報告する基本的な正常性チェック構成で十分にアプリの状態を検出できます。
基本の構成では、正常性チェック サービスを登録し、正常性チェック ミドルウェアを呼び出します。このミドルウェアが特定の URL エンドポイントにおける正常性を返します。 既定では、特定の依存関係またはサブシステムをテストする正常性チェックは登録されていません。 正常性エンドポイント URL で応答できる場合、そのアプリは正常であると見なされます。 既定の応答ライターは、プレーンテキストの応答として HealthStatus をクライアントに書き込みます。 HealthStatus
は、HealthStatus.Healthy、HealthStatus.Degraded、または HealthStatus.Unhealthy です。
正常性チェック サービスを Program.cs
の AddHealthChecks に登録します。 MapHealthChecks を呼び出して、正常性チェック エンドポイントを作成します。
次の例では、/healthz
に正常性チェック エンドポイントを作成しています。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/healthz");
app.Run();
Docker の HEALTHCHECK
Docker からは、組み込み HEALTHCHECK
ディレクティブが提供されます。これを使用し、基本的な正常性チェック構成を使用するアプリの状態を確認できます。
HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit
上の例では、curl
を使用して、/healthz
の正常性チェック エンドポイントに対して HTTP 要求を行っています。 curl
は .NET Linux コンテナー イメージには含まれていませんが、必要なパッケージを Dockerfile にインストールすることによって追加できます。 Alpine Linux に基づくイメージを使用するコンテナーでは、curl
の代わりに含まれている wget
を使用できます。
正常性チェックを作成する
正常性チェックは IHealthCheck インターフェイスを実装することで作成されます。 CheckHealthAsync メソッドによって、Healthy
、Degraded
、Unhealthy
のいずれかの正常性を示す HealthCheckResult が返されます。 結果は、構成可能なステータス コードを含むプレーンテキストの応答として書き込まれます。 構成については、「正常性チェック オプション」を参照してください。 HealthCheckResult からは、任意のキーと値のペアを返すこともできます。
次の例は、正常性チェックのレイアウトを示しています。
public class SampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
正常性チェックのロジックが CheckHealthAsync メソッドに配置されています。 前の例では、ダミー変数 isHealthy
が true
に設定されています。 isHealthy
の値が false
に設定されている場合、HealthCheckRegistration.FailureStatus 状態が返されます。
CheckHealthAsync がチェック中に例外をスローした場合、HealthReportEntry.Status が FailureStatus に設定された新しい HealthReportEntry が返されます。 この状態は AddCheck によって定義され (「正常性チェック サービスを登録する」を参照)、チェックに失敗した原因となった内部例外が含まれています。 Description は例外のメッセージに設定されます。
正常性チェック サービスを登録する
正常性チェック サービスを登録するには、Program.cs
で AddCheck を呼び出します。
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>("Sample");
次の例にある AddCheck オーバーロードでは、正常性チェックでエラーが報告されると、レポートにエラー状態 (HealthStatus) が設定されます。 エラー状態が null
(既定) に設定された場合、HealthStatus.Unhealthy が報告されます。 このオーバーロードはライブラリ作成者にとって便利です。この設定に正常性チェック実装が従う場合、正常性チェック エラーが発生したとき、ライブラリによって指示されるエラー状態がアプリによって適用されます。
"タグ" を使用して、正常性チェックをフィルター処理できます。 タグの詳細については、「正常性チェックをフィルター処理する」を参照してください。
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheck>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" });
AddCheck では、lambda 関数も実行できます。 この例では、正常性チェックにより常に正常な結果が返されます。
builder.Services.AddHealthChecks()
.AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));
AddTypeActivatedCheck を呼び出して、正常性チェックの実装に引数を渡します。 次の例では、型がアクティブ化された正常性チェックは、コンストラクターに整数と文字列を受け取ります。
public class SampleHealthCheckWithArgs : IHealthCheck
{
private readonly int _arg1;
private readonly string _arg2;
public SampleHealthCheckWithArgs(int arg1, string arg2)
=> (_arg1, _arg2) = (arg1, arg2);
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
// ...
return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
}
}
上記の正常性チェックを登録するには、整数と文字列を引数として渡して AddTypeActivatedCheck
を呼び出します。
builder.Services.AddHealthChecks()
.AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
"Sample",
failureStatus: HealthStatus.Degraded,
tags: new[] { "sample" },
args: new object[] { 1, "Arg" });
正常性チェックのルーティングを使用する
Program.cs
で、エンドポイントの URL または相対パスを使用して、エンドポイント ビルダーで MapHealthChecks
を呼び出します。
app.MapHealthChecks("/healthz");
ホストが必要
RequireHost
を呼び出して、正常性チェック エンドポイントに許可されている 1 つ以上のホストを指定します。 ホストは、punycode ではなく Unicode にする必要があります。また、ポートを含めることができます。 コレクションが指定されていない場合は、任意のホストを使用できます。
app.MapHealthChecks("/healthz")
.RequireHost("www.contoso.com:5001");
特定のポートでのみ応答するように正常性チェック エンドポイントを制限するには、RequireHost
の呼び出しでポートを指定します。 この方法は通常、サービスを監視するためのポートを公開する目的で、コンテナー環境で使用されます。
app.MapHealthChecks("/healthz")
.RequireHost("*:5001");
警告
HttpRequest.Host、RequireHost などのホスト ヘッダーに依存する API は、クライアントによるスプーフィングの対象になる可能性があります。
ホストとポートのスプーフィングを防ぐには、次のいずれかの方法を使用します。
- ポートがチェックされる場所で HttpContext.Connection (ConnectionInfo.LocalPort) を使用します。
- ホスト フィルタリングを採用します。
承認されていないクライアントがポートをスプーフィングするのを防ぐには、RequireAuthorization を呼び出します。
app.MapHealthChecks("/healthz")
.RequireHost("*:5001")
.RequireAuthorization();
詳細については、「RequireHost とルートが一致するホスト」を参照してください。
承認が必要
RequireAuthorization を呼び出して、正常性チェック要求エンドポイントで承認ミドルウェアを実行します。 RequireAuthorization
のオーバーロードには 1 つ以上の承認ポリシーを使用できます。 ポリシーが指定されていない場合は、既定の承認ポリシーが使用されます。
app.MapHealthChecks("/healthz")
.RequireAuthorization();
クロスオリジン要求 (CORS) の有効化
ブラウザーから手動で正常性チェックを実行することは一般的なシナリオではありませんが、正常性チェック エンドポイントで RequireCors
を呼び出して CORS ミドルウェアを有効にすることができます。 RequireCors
のオーバーロードには、CORS ポリシー ビルダーのデリゲート (CorsPolicyBuilder
) またはポリシー名を使用できます。 詳細については、「ASP.NET Core でクロスオリジン要求 (CORS) を有効にする」を参照してください。
正常性チェック オプション
HealthCheckOptions では、正常性チェックの動作をカスタマイズできます。
正常性チェックをフィルター処理する
既定では、正常性チェック ミドルウェアによって、登録済みの正常性チェックがすべて実行されます。 正常性チェックのサブセットを実行するには、Predicate オプションにブール値を返す関数を指定します。
次の例では、正常性チェックのフィルター処理を行い、sample
タグが付けられているものだけが実行されるようにします。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});
HTTP 状態コードをカスタマイズする
ResultStatusCodes を使用し、HTTP 状態コードに対する正常性状態のマッピングをカスタマイズします。 次の StatusCodes 代入はミドルウェアによって使用される既定値です。 要件に合わせて状態コード値を変更します。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
キャッシュ ヘッダーを非表示にする
AllowCachingResponses によって、応答キャッシュを禁止する目的で、正常性チェック ミドルウェアによって HTTP ヘッダーがプローブ応答に追加されるかどうかが制御されます。 値が false
(既定) の場合、応答キャッシュを禁止する目的で、ミドルウェアによってヘッダー Cache-Control
、Expires
、Pragma
が設定またはオーバーライドされます。 値が true
の場合、応答のキャッシュ ヘッダーがミドルウェアによって変更されることはありません。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
AllowCachingResponses = true
});
出力をカスタマイズする
正常性チェック レポートの出力をカスタマイズするには、HealthCheckOptions.ResponseWriter プロパティを、応答の書き込み先のデリゲートに設定します。
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
ResponseWriter = WriteResponse
});
既定の委任では、文字列値 HealthReport.Status
を含む、最小のプレーンテキスト応答が書き込まれます。 次のカスタム デリゲートでは、System.Text.Json を使用してカスタム JSON 応答が出力されます。
private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
context.Response.ContentType = "application/json; charset=utf-8";
var options = new JsonWriterOptions { Indented = true };
using var memoryStream = new MemoryStream();
using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
{
jsonWriter.WriteStartObject();
jsonWriter.WriteString("status", healthReport.Status.ToString());
jsonWriter.WriteStartObject("results");
foreach (var healthReportEntry in healthReport.Entries)
{
jsonWriter.WriteStartObject(healthReportEntry.Key);
jsonWriter.WriteString("status",
healthReportEntry.Value.Status.ToString());
jsonWriter.WriteString("description",
healthReportEntry.Value.Description);
jsonWriter.WriteStartObject("data");
foreach (var item in healthReportEntry.Value.Data)
{
jsonWriter.WritePropertyName(item.Key);
JsonSerializer.Serialize(jsonWriter, item.Value,
item.Value?.GetType() ?? typeof(object));
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndObject();
jsonWriter.WriteEndObject();
}
return context.Response.WriteAsync(
Encoding.UTF8.GetString(memoryStream.ToArray()));
}
正常性チェック API には、複雑な JSON の戻り値の形式に対する組み込みのサポートが用意されていません。この形式は、選択した監視システムに固有のものであるためです。 必要に応じて、上記の例の応答をカスタマイズします。 System.Text.Json
を使用した JSON シリアル化の詳細については、.NET で JSON をシリアル化および逆シリアル化する方法に関する記事をご覧ください。
データベース プローブ
正常性チェックでは、データベースが通常どおり応答しているかどうかを示すブール値テストとして実行されるよう、データベース クエリを指定できます。
ASP.NET Core アプリ用の正常性チェック ライブラリ AspNetCore.Diagnostics.HealthChecks
には、SQL Server データベースに対して実行される正常性チェックが含まれています。 AspNetCore.Diagnostics.HealthChecks
によってデータベースに対して SELECT 1
クエリが実行され、データベースへの接続が正常であることが確認されます。
警告
クエリでデータベース接続を確認するとき、すぐに返されるクエリを選択します。 このクエリ手法には、データベースをオーバーロードし、そのパフォーマンスを低下させるというリスクがあります。 ほとんどの場合、テスト クエリは実行する必要がありません。 データベースに正常に接続できれば十分です。 クエリを実行する必要があれば、SELECT 1
など、単純な SELECT クエリを選択してください。
この SQL Server 正常性チェックを使用するには、AspNetCore.HealthChecks.SqlServer
NuGet パッケージへのパッケージ参照を含めます。 次の例では、SQL Server 正常性チェックを登録します。
builder.Services.AddHealthChecks()
.AddSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection"));
Note
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
Entity Framework Core DbContext プローブ
DbContext
チェックでは、EF CoreDbContext
に対して構成されているデータベースとアプリとが通信できることが確認されます。 DbContext
チェックは、次のようなアプリでサポートされています。
- Entity Framework (EF) Core を使用する。
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
NuGet パッケージへのパッケージ参照を含めます。
AddDbContextCheck によって DbContext の正常性チェックが登録されます。 DbContext
は TContext
としてメソッドに指定されます。 オーバーロードはエラー状態、タグ、カスタム テスト クエリの設定に利用できます。
既定では:
DbContextHealthCheck
は、EF Core のCanConnectAsync
メソッドを呼び出します。AddDbContextCheck
メソッドのオーバーロードを使用して正常性を確認するときに実行される操作をカスタマイズできます。- 正常性チェックの名前は
TContext
型の名前になります。
次の例では、DbContext
と、これに関連付けられている DbContextHealthCheck
を登録します。
builder.Services.AddDbContext<SampleDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddHealthChecks()
.AddDbContextCheck<SampleDbContext>();
対応性と活動性に区分されるプローブ
一部のホスティング シナリオでは、2 つのアプリ状態を区別する一組の正常性チェックが使用されます。
- "対応性" は、アプリが通常どおり実行されているが、要求を受け取る準備ができていないのか、あるいはそうではないのかを示します。
- "活動性" は、アプリがクラッシュしたため、再起動する必要があるのかどうかを示します。
次に例を示します。アプリでは、大きな構成ファイルをダウンロードしないと、要求を処理する準備ができません。 初回ダウンロードに失敗した場合、アプリを再起動することは望みません。アプリはファイルのダウンロードを数回再試行する可能性があるためです。 liveness probe を使用し、プロセスの活動性を記述します。他のチェックは実行されません。 また、構成ファイルのダウンロードが完了する前は、要求がアプリに送信されないようにします。 "対応性プローブ" を使用し、ダウンロードが成功し、要求を受け取る準備がアプリにできるまで、"準備できていない" 状態を示します。
次のバックグラウンド タスクでは、15 秒ほどかかるスタートアップ プロセスをシミュレートします。 完了すると、このタスクによって StartupHealthCheck.StartupCompleted
プロパティが true に設定されます。
public class StartupBackgroundService : BackgroundService
{
private readonly StartupHealthCheck _healthCheck;
public StartupBackgroundService(StartupHealthCheck healthCheck)
=> _healthCheck = healthCheck;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Simulate the effect of a long-running task.
await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);
_healthCheck.StartupCompleted = true;
}
}
StartupHealthCheck
は、実行時間の長いスタートアップ タスクの完了をレポートし、バックグラウンド サービスによって設定される StartupCompleted
プロパティを公開します。
public class StartupHealthCheck : IHealthCheck
{
private volatile bool _isReady;
public bool StartupCompleted
{
get => _isReady;
set => _isReady = value;
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
if (StartupCompleted)
{
return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
}
return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
}
}
ホステッド サービスと共に Program.cs
で正常性チェックが AddCheck に登録されます。 ホステッド サービスでは正常性チェックにプロパティを設定する必要があるため、正常性チェックはシングルトンとしてサービス コンテナーにも登録されます。
builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();
builder.Services.AddHealthChecks()
.AddCheck<StartupHealthCheck>(
"Startup",
tags: new[] { "ready" });
2 つの異なる正常性チェック エンドポイントを作成するには、MapHealthChecks
を 2 回呼び出します。
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
Predicate = _ => false
});
前の例では、次の正常性チェック エンドポイントを作成しています。
- 対応性チェックの場合は
/healthz/ready
。 対応性チェックでは、ready
タグが付けられているものに正常性チェックが絞り込まれます。 - 活動性チェックの場合は
/healthz/live
。 この活動性チェックでは、HealthCheckOptions.Predicate デリゲートでfalse
を返すことによって、すべての正常性チェックを除外します。 正常性チェックのフィルター処理の詳細については、この記事の「正常性チェックをフィルター処理する」を参照してください。
スタートアップ タスクが完了する前に、/healthz/ready
エンドポイントから Unhealthy
状態がレポートされます。 スタートアップ タスクが完了したら、このエンドポイントから Healthy
状態がレポートされます。 /healthz/live
エンドポイントは、すべてのチェックを除外し、すべての呼び出しに対して Healthy
状態をレポートします。
Kubernetes の例
対応性チェックと活動性チェックを使い分けることは、Kubernetes などの環境で便利です。 Kubernetes では、要求を受け入れる前に、基礎をなすデータベースの可用性テストなど、時間のかかるスタートアップ作業の実行がアプリに要求されることがあります。 別個のチェックを利用することで、アプリは機能しているがまだ準備ができていないか、あるいはアプリが起動に失敗したかをオーケストレーターは区別できます。 Kubernetes の対応性プローブと活動性プローブに関する詳細については、Kubernetes ドキュメントの「Configure Liveness and Readiness Probes」 (活動性プローブと対応性プローブを設定する) を参照してください。
次の例では、Kubernetes 対応性プローブの構成を確認できます。
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /healthz/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
正常性チェック ライブラリを配布する
正常性チェックをライブラリとして配布するには:
スタンドアロン クラスとして IHealthCheck インターフェイスを実装する正常性チェックを記述します。 このクラスは、設定データにアクセスする目的で依存関係挿入 (DI)、型のアクティブ化、名前付きオプションに依存できます。
拡張メソッドを記述します。拡張メソッドを使用するアプリがその
Program.cs
メソッドで呼び出すパラメーターを指定します。arg1
とarg2
をコンストラクター パラメーターとして受け取る、次の正常性チェックの例を考えてみましょう。public SampleHealthCheckWithArgs(int arg1, string arg2) => (_arg1, _arg2) = (arg1, arg2);
先のシグネチャは、正常性チェック プローブ ロジックを処理するためには、正常性チェックにカスタム データが必要であることを示しています。 正常性チェックが拡張メソッドに登録されたときに正常性チェック インスタンスを作成するための委任にデータが提供されます。 次の例では、呼び出し元によって以下が指定されます。
arg1
: 正常性チェックの整数データ ポイント。arg2
: 正常性チェックの文字列引数。name
: 正常性チェック名 (省略可能)。null
の場合、既定値が使用されます。failureStatus
: エラー状態に対してレポートされる HealthStatus (省略可能)。null
の場合、HealthStatus.Unhealthy が使用されます。tags
: タグのIEnumerable<string>
コレクション (省略可能)。
public static class SampleHealthCheckBuilderExtensions { private const string DefaultName = "Sample"; public static IHealthChecksBuilder AddSampleHealthCheck( this IHealthChecksBuilder healthChecksBuilder, int arg1, string arg2, string? name = null, HealthStatus? failureStatus = null, IEnumerable<string>? tags = default) { return healthChecksBuilder.Add( new HealthCheckRegistration( name ?? DefaultName, _ => new SampleHealthCheckWithArgs(arg1, arg2), failureStatus, tags)); } }
正常性チェック パブリッシャー
サービス コンテナーに IHealthCheckPublisher が追加されると、正常性チェック システムにより定期的に正常性チェックが実行され、結果と共に PublishAsync が呼び出されます。 このプロセスは、正常性を判断する目的で監視システムを定期的に呼び出すことを各プロセスに求めるプッシュベースの監視システム シナリオで便利です。
HealthCheckPublisherOptions を使うと次を設定できます。
- Delay:アプリが起動した後、IHealthCheckPublisher インスタンスを実行する前に適用される初期遅延です。 遅延はスタートアップ時に一度だけ適用され、後の繰り返しには適用されません。 既定値は 5 秒です。
- Period:IHealthCheckPublisher を実行する期間です。 既定値は 30 秒です。
- Predicate:Predicate が
null
(既定値) の場合、正常性チェック パブリッシャー サービスにより登録済みのすべての正常性チェックが実行されます。 正常性チェックのサブセットを実行するには、チェックのセットをフィルター処理する関数を指定します。 述語は期間ごとに評価されます。 - Timeout:すべての IHealthCheckPublisher インスタンスに対する正常性チェックの実行のタイムアウトです。 タイムアウトなしで実行するには InfiniteTimeSpan を使います。 既定値は 30 秒です。
次の例は、正常性パブリッシャーのレイアウトを示しています。
public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
// ...
}
else
{
// ...
}
return Task.CompletedTask;
}
}
HealthCheckPublisherOptions クラスには、正常性チェック パブリッシャーの動作を構成するためのプロパティが用意されています。
次の例では、正常性チェック パブリッシャーをシングルトンとして登録し、HealthCheckPublisherOptions を構成します。
builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});
builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();
Note
AspNetCore.Diagnostics.HealthChecks
には、Application Insights など、いくつかのシステムのパブリッシャーが含まれます。
Microsoft は、AspNetCore.Diagnostics.HealthChecks
の保守管理もサポートも行っていません。
依存関係の挿入と正常性チェック
正常性チェック クラス内の特定の Type
のインスタンスを使用するために、依存関係の挿入を使用することができます。 依存関係の挿入は、正常性チェックにオプションまたはグローバル構成を挿入する場合に役立ちます。 依存関係の挿入を使用することは、正常性チェックを構成するための一般的なシナリオでは "ありません"。 通常、各正常性チェックは実際のテストに完全に固有のものであり、IHealthChecksBuilder
拡張メソッドを使用して構成されます。
次の例は、依存関係の挿入を使用して構成オブジェクトを取得する正常性チェックのサンプルを示したものです。
public class SampleHealthCheckWithDI : IHealthCheck
{
private readonly SampleHealthCheckWithDiConfig _config;
public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
=> _config = config;
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken = default)
{
var isHealthy = true;
// use _config ...
if (isHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("A healthy result."));
}
return Task.FromResult(
new HealthCheckResult(
context.Registration.FailureStatus, "An unhealthy result."));
}
}
SampleHealthCheckWithDiConfig
と正常性チェックをサービス コンテナーに追加する必要があります。
builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
.AddCheck<SampleHealthCheckWithDI>(
"With Dependency Injection",
tags: new[] { "inject" });
UseHealthChecks と MapHealthChecks
呼び出し元が正常性チェックにアクセスできるようにするには、次の 2 つの方法があります。
- UseHealthChecks は、ミドルウェア パイプラインで正常性チェック要求を処理するためのミドルウェアを登録します。
- MapHealthChecks は、正常性チェック エンドポイントを登録します。 エンドポイントは、アプリ内の他のエンドポイントと合わせてマッチされ実行されます。
UseHealthChecks
上で MapHealthChecks
を使用する利点は、認可のようなエンドポイント認識ミドルウェアを使用し、マッチ ポリシーをより細かい粒度で制御できる点です。 MapHealthChecks
上で UseHealthChecks
を使用する主な利点は、ミドルウェア パイプラインで正常性チェックが実行される場所を正確に制御できることです。
- 要求が正常性チェック エンドポイントとマッチすると、パイプラインを終了させます。 ショートサーキットはログやその他のミドルウェアなどの不要な作業を防ぐため、多くの場合に望ましいものです。
- 主に、パイプラインで正常性チェック ミドルウェアを構成するために使用されます。
null
または空のPathString
を持つポート上の任意のパスとマッチできます。 指定したポートに対して行われた任意の要求に対して正常性チェックの実行を許可します。- ソース コード
MapHealthChecks は次のことを許可します。
- 正常性チェック用の特定のルートまたはエンドポイントのマッピング。
- 正常性チェック エンドポイントにアクセスできる URL またはパスのカスタマイズ。
- ルートまたは構成が異なる複数の正常性チェック エンドポイントのマッピング。 複数エンドポイントのサポート:
- さまざまな種類の正常性チェックまたはコンポーネントに対して個別のエンドポイントを有効にします。
- アプリの正常性のさまざまな側面を区別したり、正常性チェックのサブセットに特定の構成を適用したりするために使用されます。
- ソース コード
その他のリソース
- サンプル コードを表示またはダウンロードします (ダウンロード方法)。
注意
この記事は部分的に人工知能を活用して作成しました。 公開する前に作成者が内容を確認し、必要に応じて修正しました。 AI によって生成されたコンテンツを Microsoft Learn で使用するための原則に関するページを参照してください。
ASP.NET Core