.NET Core Worker Serviceにヘルスチェックを実装する最良の方法は何ですか?
サービスはdocker内で実行され、サービスの状態を確認できる必要があります。
Microsoft.NET.Sdk.Workerを保持することも検討する必要があると思います。
ヘルスチェックのためだけにSDK全体を変更しないでください。
次に、バックグラウンドサービスを作成して(メインワーカーと同じように)、ファイルを更新して、たとえば現在のタイムスタンプを書き込むことができます。バックグラウンドヘルスチェックワーカーの例は次のとおりです。
public class HealthCheckWorker : BackgroundService
{
private readonly int _intervalSec;
private readonly string _healthCheckFileName;
public HealthCheckWorker(string healthCheckFileName, int intervalSec)
{
this._intervalSec = intervalSec;
this._healthCheckFileName = healthCheckFileName;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (true)
{
File.WriteAllText(this._healthCheckFileName, DateTime.UtcNow.ToString());
await Task.Delay(this._intervalSec * 1000, stoppingToken);
}
}
}
次に、次のような拡張メソッドを追加できます。
public static class HealthCheckWorkerExtensions
{
public static void AddHealthCheck(this IServiceCollection services,
string healthCheckFileName, int intervalSec)
{
services.AddHostedService<HealthCheckWorker>(x => new HealthCheckWorker(healthCheckFileName, intervalSec));
}
}
これにより、ヘルスチェックサポートをサービスに追加できます
.ConfigureServices(services =>
{
services.AddHealthCheck("hc.txt", 5);
})
これを行う別の方法は、IHealthCheckPublisher
を実装することです。
このアプローチの利点は、既存のIHealthCheck
sを再利用する機能、またはIHealthCheck
インターフェイスに依存するサードパーティライブラリとの統合( これ など)です。
まだターゲットにしていますがMicrosoft.NET.Sdk.Web
SDKとして、asp.netの詳細を追加する必要はありません。
次に例を示します。
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services
.AddHealthChecks()
.AddCheck<RedisHealthCheck>("redis_health_check")
.AddCheck<RfaHealthCheck>("rfa_health_check");
services.AddSingleton<IHealthCheckPublisher, HealthCheckPublisher>();
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(5);
options.Period = TimeSpan.FromSeconds(5);
});
});
}
public class HealthCheckPublisher : IHealthCheckPublisher
{
private readonly string _fileName;
private HealthStatus _prevStatus = HealthStatus.Unhealthy;
public HealthCheckPublisher()
{
_fileName = Environment.GetEnvironmentVariable(EnvVariableNames.DOCKER_HEALTHCHECK_FILEPATH) ??
Path.GetTempFileName();
}
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
// AWS will check if the file exists inside of the container with the command
// test -f $DOCKER_HEALTH_CHECK_FILEPATH
var fileExists = _prevStatus == HealthStatus.Healthy;
if (report.Status == HealthStatus.Healthy)
{
if (!fileExists)
{
using var _ = File.Create(_fileName);
}
}
else if (fileExists)
{
File.Delete(_fileName);
}
_prevStatus = report.Status;
return Task.CompletedTask;
}
}