背景服務和啟動工作
建置 Orleans 應用程式時,您通常需要在應用程式啟動時執行背景作業或初始化元件。
啟動工作可用來在存放區啟動時,於接收要求開始之前或之後,執行初始化工作。 常見的使用案例包括:
- 初始化粒紋狀態或預先載入數據
- 設定外部服務連線
- 執行資料庫移轉
- 驗證組態
- 快取預熱
使用 BackgroundService (建議)
建議的方法是使用 .NET BackgroundService 或 IHostedService
。 如需詳細資訊,請參閱 ASP.NET Core 檔中具有託管服務的
以下是每隔 5 秒 Ping 一次粒紋的範例:
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.");
}
}
}
註冊順序相當重要,因為新增至主機產生器的服務會依註冊的順序逐一啟動。 您可以註冊背景服務,如下所示:
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' 啟動工作
注意
雖然仍支持啟動工作,但建議改用 BackgroundService
或 IHostedService
,因為它們是執行背景工作的常見 .NET 裝載機制。
警告
從啟動工作擲出的任何異常都會在silo日誌中報告,並將導致silo停止。 這個快速失敗策略有助於在測試期間偵測設定和引導程序問題,而不是在稍後造成非預期的問題,但這也表示,啟動工作中的暫時性失敗可能會導致主機暫時無法使用。
如果您需要使用內建啟動工作系統,您可以設定它們,如下所示:
註冊代表
可以將委派使用適當的 AddStartupTask 擴充方法在 ISiloBuilder上註冊為啟動程序。
siloBuilder.AddStartupTask(
async (IServiceProvider services, CancellationToken cancellation) =>
{
var grainFactory = services.GetRequiredService<IGrainFactory>();
var grain = grainFactory.GetGrain<IMyGrain>("startup-task-grain");
await grain.Initialize();
});
註冊 IStartupTask
實作
您可以在 ISiloBuilder上使用 AddStartupTask 擴充方法,實作 IStartupTask 介面並註冊為啟動工作。
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>();