次の方法で共有


バックグラウンド サービスとスタートアップ タスク

Orleans アプリケーションをビルドするときは、多くの場合、アプリケーションの起動時にバックグラウンド操作を実行するか、コンポーネントを初期化する必要があります。

スタートアップ タスクは、サイロの開始時、要求の受け入れ開始前または開始後に初期化作業を実行するために使用できます。 一般的なユース ケースは次のとおりです。

  • グレイン状態の初期化またはデータの事前読み込み
  • 外部サービス接続の設定
  • データベース移行の実行
  • 構成の検証
  • キャッシュのウォームアップ

推奨される方法は、.NET BackgroundService または IHostedServiceを使用することです。 詳細については、ASP.NET Core ドキュメントのホストされたサービスを使用した バックグラウンド タスクを参照してください。

5秒ごとにグレインに信号を送る例を示します。

public class GrainPingService : BackgroundService
{
    private readonly IGrainFactory _grainFactory;
    private readonly ILogger<GrainPingService> _logger;

    public GrainPingService(
        IGrainFactory grainFactory,
        ILogger<GrainPingService> logger)
    {
        _grainFactory = grainFactory;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    _logger.LogInformation("Pinging grain...");
                    var grain = _grainFactory.GetGrain<IMyGrain>("ping-target");
                    await grain.Ping();
                }
                catch (Exception ex) when (ex is not OperationCanceledException)
                {
                    // Log the error but continue running
                    _logger.LogError(ex, "Failed to ping grain. Will retry in 5 seconds.");
                }

                await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
            }
        }
        catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
        {
            // Ignore cancellation during shutdown.
        }
        finally
        {
            _logger.LogInformation("Grain ping service is shutting down.");
        }
    }
}

登録順序は重要です。ホスト ビルダーに追加されたサービスは、登録された順序で 1 つずつ開始されるためです。 バックグラウンド サービスは次のように登録できます。

var builder = WebApplication.CreateBuilder(args);

// Configure Orleans first
builder.UseOrleans(siloBuilder => 
{
    // Orleans configuration...
});

// Register the background service after calling 'UseOrleans' to make it start once Orleans has started.
builder.Services.AddHostedService<GrainPingService>();

var app = builder.Build();

バックグラウンド サービスは、アプリケーションの起動時に自動的に開始され、アプリケーションが停止すると正常にシャットダウンされます。

IHostedService の使用

継続的なバックグラウンド操作が不要な単純なシナリオでは、IHostedService を直接実装できます。

public class GrainInitializerService : IHostedService
{
    private readonly IGrainFactory _grainFactory;
    private readonly ILogger<GrainInitializerService> _logger;

    public GrainInitializerService(
        IGrainFactory grainFactory,
        ILogger<GrainInitializerService> logger)
    {
        _grainFactory = grainFactory;
        _logger = logger;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Initializing grains...");
        var grain = _grainFactory.GetGrain<IMyGrain>("initializer");
        await grain.Initialize();
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

同じ方法で登録します。

builder.Services.AddHostedService<GrainInitializerService>();

Orleans' スタートアップ タスク

手記

スタートアップ タスクは引き続きサポートされていますが、バックグラウンド タスクを実行するための一般的な .NET ホスティング メカニズムであるため、代わりに BackgroundService または IHostedService を使用することをお勧めします。

警告

スタートアップ タスクからスローされた例外はすべてサイロ ログに報告され、サイロは停止されます。 このフェイルファーストアプローチは、後で予期しない問題を引き起こすのではなく、テスト中に構成とブートストラップの問題を検出するのに役立ちますが、スタートアップ タスクの一時的な障害によってホストが使用できなくなる可能性もあります。

組み込みのスタートアップ タスク システムを使用する必要がある場合は、次のように構成できます。

デリゲートを登録する

デリゲートは、ISiloBuilderの適切な AddStartupTask 拡張メソッドを使用して、スタートアップ タスクとして登録できます。

siloBuilder.AddStartupTask(
    async (IServiceProvider services, CancellationToken cancellation) =>
    {
        var grainFactory = services.GetRequiredService<IGrainFactory>();
        var grain = grainFactory.GetGrain<IMyGrain>("startup-task-grain");
        await grain.Initialize();
    });

IStartupTask 実装を登録する

IStartupTask インターフェイスは、ISiloBuilderAddStartupTask 拡張メソッドを使用して、スタートアップ タスクとして実装および登録できます。

public class CallGrainStartupTask : IStartupTask
{
    private readonly IGrainFactory _grainFactory;

    public CallGrainStartupTask(IGrainFactory grainFactory) =>
        _grainFactory = grainFactory;

    public async Task Execute(CancellationToken cancellationToken)
    {
        var grain = _grainFactory.GetGrain<IMyGrain>("startup-task-grain");
        await grain.Initialize();
    }
}

スタートアップ タスクを次のように登録します。

siloBuilder.AddStartupTask<CallGrainStartupTask>();