次の方法で共有


C# での .NET アプリの正常性チェック

分散システムでの正常性チェックとは、個々のノードまたはサービスの状態、可用性、パフォーマンスを定期的に評価することです。 こうしたチェックにより、システムが正しく効率的かつ確実に機能するようになります。 正常性チェックはシステムの信頼性を確保するうえで非常に重要で、通常、意思決定と是正措置のために分析された結果を使用して定期的に実行されます。

考えられる正常性チェック状態の結果を次に示します。

さらに、正常性チェックでは通常、さまざまな診断メトリックが報告されます。 詳細については、診断メトリック: Microsoft.Extensions.Diagnostics.HealthChecks に関するページを参照してください。

リソース使用率の正常性チェック

.NET アプリのリソース使用率に対して正常性チェックを実行するには、Microsoft.Extensions.Diagnostics.HealthChecks.ResourceUtilization へのパッケージ参照を追加します。 IServiceCollection インスタンスで、AddHealthChecks から AddResourceUtilizationHealthCheck への呼び出しをチェーンします。 次の例は、AddResourceUtilizationHealthCheck 拡張メソッドを使用して、リソース使用率の正常性チェックを IServiceCollection インスタンスに追加する方法を示しています。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddHealthChecks()
    .AddResourceUtilizationHealthCheck();

var app = builder.Build();

var healthCheckService = app.Services.GetRequiredService<HealthCheckService>();

var result = await healthCheckService.CheckHealthAsync();

Console.WriteLine($"{result.Status} {result.TotalDuration}");

app.Run();

上記のコードでは次の操作が行われます。

  • 新しい HostApplicationBuilder インスタンスを作成します。
  • AddHealthChecks 呼び出しから AddResourceUtilizationHealthCheck 拡張メソッドへの呼び出しをチェーンすることで、リソース使用率の正常性チェックを追加します。
  • IHost インスタンスを app 変数として構築します。
  • サービス プロバイダーから HealthCheckService クラスのインスタンスを取得します。
  • 正常性チェックを実行し、結果を表示します。
  • アプリケーションを実行します。

アプリケーションの有効期間の正常性チェック

IHostApplicationLifetime のアプリケーションの有効期間イベントに対して正常性チェックを実行するには、Microsoft.Extensions.Diagnostics.HealthChecks.Common NuGet パッケージで使用できる AddApplicationLifecycleHealthCheck 拡張メソッドを使用します。

このプロバイダーは、アプリケーションは、完全にアクティブな場合にのみ正常であることを示します。 プロバイダーは、アプリケーションが開始されたことが有効期間オブジェクトによって示されるまで、そのアプリケーションを異常として報告します。 アプリケーションによってシャットダウンが開始されると、プロバイダーはアプリケーションを異常として報告します。

このライブラリは HealthCheckService を公開し、コンシューマーがいつでも正常性チェックを要求できるようにします。 ExampleService の次の実装を見てみましょう。

using System.Runtime.CompilerServices;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

internal class ExampleLifecycle(
    HealthCheckService healthCheckService,
    ILogger<ExampleLifecycle> logger) : IHostedLifecycleService
{
    Task IHostedService.StartAsync(
        CancellationToken cancellationToken) =>
        CheckHealthAsync(cancellationToken: cancellationToken);

    Task IHostedLifecycleService.StartedAsync(
        CancellationToken cancellationToken) =>
        CheckHealthAsync(cancellationToken: cancellationToken);

    Task IHostedLifecycleService.StartingAsync(
        CancellationToken cancellationToken) =>
        CheckHealthAsync(cancellationToken: cancellationToken);

    Task IHostedService.StopAsync(
        CancellationToken cancellationToken) =>
        CheckHealthAsync(cancellationToken: cancellationToken);

    Task IHostedLifecycleService.StoppedAsync(
        CancellationToken cancellationToken) =>
        CheckHealthAsync(cancellationToken: cancellationToken);

    Task IHostedLifecycleService.StoppingAsync(
        CancellationToken cancellationToken) =>
        CheckHealthAsync(cancellationToken: cancellationToken);

    public Task ReadyAsync() => CheckHealthAsync();

    private async Task CheckHealthAsync(
         [CallerMemberName] string eventName = "",
         CancellationToken cancellationToken = default)
    {
        HealthReport result =
            await healthCheckService.CheckHealthAsync(cancellationToken);

        logger.LogInformation(
            "{EventName}: {Status}", eventName, result.Status);
    }
}

上記のコードでは次の操作が行われます。

  • IHostedService インターフェイスを実装する新しい ExampleLifecycle クラスを定義します。
  • 次のパラメーターを受け入れるプライマリ コンストラクターを定義します。
  • IHostedLifecycleService インターフェイスを実装し、各メソッドで CheckHealthAsync メソッドを呼び出します。
  • CheckHealthAsync メソッドを呼び出す ReadyAsync メソッドを定義します。
  • 呼び出し元の名前とキャンセル トークンをキャプチャし、HealthCheckService インスタンスから正常性チェックを要求するカスタム CheckHealthAsync メソッドを定義します。 その後、result がログに記録されます。

正常性チェック サービスによって状態 HealthStatus.Healthy が報告されるのは、アプリが開始されてから停止が呼び出されるまでの間にに限られます。 次の Program.cs コードを考えてみてください。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

var healthChecksBuilder = builder.Services
    .AddHostedService<ExampleLifecycle>()
    .AddHealthChecks()
    .AddApplicationLifecycleHealthCheck();

// You could use the healthChecksBuilder instance to add more checks...

var app = builder.Build();

var services = app.Services.GetRequiredService<IEnumerable<IHostedService>>();

await Task.WhenAll(DelayAndReportAsync(services), app.RunAsync());

static async Task DelayAndReportAsync(IEnumerable<IHostedService> services)
{
    // Ensure app started...
    await Task.Delay(500);

    var service = services.FirstOrDefault(static s => s is ExampleLifecycle);
    if (service is ExampleLifecycle example)
    {
        await example.ReadyAsync();
    }
}

上記のコードでは次の操作が行われます。

  • builder 変数として新しい割り当て先 HostApplicationBuilder インスタンスを作成します。
  • ExampleService をアプリの唯一の IHostedService として登録します。
  • AddApplicationLifecycleHealthCheck 拡張メソッドへの AddHealthChecks 呼び出しによって返された IHealthChecksBuilder インスタンスからの呼び出しをチェーンすることで、IHostApplicationLifetime のアプリケーションの有効期間イベントについて正常性チェックを追加します。
    • healthChecksBuilder インスタンスを使用して、さらに正常性チェックを追加できます。
  • IHost インスタンスを app 変数として構築します。
  • サービス プロバイダーから IHostedService を取得します。これは ExampleService インスタンスです。
  • Task.WhenAll を呼び出して、次の 2 つのタスク参照を指定します。
    • DelayAndReportAsync メソッド。500 ミリ秒遅延し、その後、ExampleService インスタンスで ReadyAsync メソッドを呼び出し、正常性チェックを評価します。
    • RunAsync(IHost, CancellationToken) メソッド。app を開始します。

アプリは次の順序でログを出力し、ライフサイクル イベントに関連する正常性チェック状態を報告します。

  1. StartingAsync: 異常
  2. StartAsync: 異常
  3. StartedAsync: 異常
  4. ReadyAsync: 正常
  5. StoppingAsync: 異常
  6. StopAsync: 異常
  7. StoppedAsync: 異常

言い換えると、このプロバイダーでは、アプリケーション インスタンスがトラフィックを受信するのは、準備ができたときだけになります。 ASP.NET Core を使用して Web アプリを開発している場合は、使用できる正常性チェック ミドルウェアがあります。 詳細については、「ASP.NET Core の正常性チェック」を参照してください。

関連項目