Usługi działające w tle i zadania startowe
Podczas kompilowania aplikacji Orleans często trzeba wykonywać operacje w tle lub inicjować składniki podczas uruchamiania aplikacji.
Zadania uruchamiania mogą być używane do przeprowadzania inicjalizacji podczas uruchamiania silosu, przed lub po rozpoczęciu akceptowania żądań. Typowe przypadki użycia to:
- Inicjowanie stanu ziarna lub wstępne ładowanie danych
- Konfigurowanie połączeń usług zewnętrznych
- Przeprowadzanie migracji bazy danych
- Weryfikowanie konfiguracji
- Rozgrzewanie pamięci podręcznych
Korzystanie z usługi BackgroundService (zalecane)
Zalecanym podejściem jest użycie .NET BackgroundService lub IHostedService
. Aby uzyskać więcej informacji, zapoznaj się z dokumentacją dotyczącą zadań w tle z użyciem hostowanych usług w ASP.NET Core.
Oto przykład: polecenie ping jest wysyłane do ziarna co 5 sekund.
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.");
}
}
}
Kolejność rejestracji jest znacząca, ponieważ usługi dodane do konstruktora hosta są uruchamiane pojedynczo, w kolejności ich rejestracji. Usługę w tle można zarejestrować w następujący sposób:
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();
Usługa w tle zostanie uruchomiona automatycznie po uruchomieniu aplikacji i zostanie bezpiecznie zamknięta po zatrzymaniu aplikacji.
Korzystanie z usługi IHostedService
W przypadku prostszych scenariuszy, w których nie potrzebujesz ciągłej operacji w tle, można zaimplementować IHostedService
bezpośrednio:
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;
}
}
Zarejestruj go w taki sam sposób:
builder.Services.AddHostedService<GrainInitializerService>();
zadania startowe Orleans
Notatka
Mimo że zadania uruchamiania są nadal obsługiwane, zalecamy korzystanie z BackgroundService
lub IHostedService
, ponieważ stanowią one zalecany mechanizm hostingu .NET do uruchamiania zadań w tle.
Ostrzeżenie
Wszelkie wyjątki z zadania startowego zostaną odnotowane w dzienniku silosu i zatrzymają silos. Podejście typu 'fail-fast' pomaga wykrywać problemy z konfiguracją i uruchamianiem podczas testowania, co zapobiega ich nieoczekiwanemu wystąpieniu w przyszłości. Jednakże może to również oznaczać, że przejściowe błędy w zadaniu uruchamiania spowodują niedostępność hosta.
Jeśli musisz użyć wbudowanego systemu zadań uruchamiania, możesz je skonfigurować w następujący sposób:
Rejestrowanie pełnomocnika
Delegata można zarejestrować jako zadanie startowe, używając odpowiedniej metody rozszerzenia AddStartupTask w ISiloBuilder.
siloBuilder.AddStartupTask(
async (IServiceProvider services, CancellationToken cancellation) =>
{
var grainFactory = services.GetRequiredService<IGrainFactory>();
var grain = grainFactory.GetGrain<IMyGrain>("startup-task-grain");
await grain.Initialize();
});
Zarejestruj implementację IStartupTask
Interfejs IStartupTask można zaimplementować i zarejestrować jako zadanie uruchamiania przy użyciu metody rozszerzenia AddStartupTask w ISiloBuilder.
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();
}
}
Zarejestruj zadanie uruchamiania w następujący sposób:
siloBuilder.AddStartupTask<CallGrainStartupTask>();