Udostępnij za pośrednictwem


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

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>();