Compartir vía


Servicios en segundo plano y tareas de inicio

Al compilar aplicaciones Orleans, a menudo es necesario realizar operaciones en segundo plano o inicializar componentes cuando se inicia la aplicación.

Las tareas de inicio se pueden usar para realizar el trabajo de inicialización cuando se inicia un silo, antes o después de que comience a aceptar solicitudes. Entre los casos de uso comunes se incluyen:

  • Inicialización del estado de grano o precarga de datos
  • Configuración de conexiones de servicio externo
  • Realización de migraciones de bases de datos
  • Validación de la configuración
  • Calentamiento de cachés

El enfoque recomendado es usar .NET BackgroundService o IHostedService. Consulte la documentación de Tareas en segundo plano con servicios hospedados en ASP.NET Core para obtener más información.

Este es un ejemplo que hace ping a un grano cada 5 segundos:

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.");
        }
    }
}

El orden de registro es significativo, ya que los servicios agregados al generador de hosts se inician uno a uno, en el orden en que se registran. Puede registrar el servicio en segundo plano de la siguiente manera:

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

El servicio en segundo plano se iniciará automáticamente cuando se inicie la aplicación y se apagará correctamente cuando se detenga la aplicación.

Uso de IHostedService

Para escenarios más sencillos en los que no necesita una operación en segundo plano continua, puede implementar IHostedService directamente:

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;
    }
}

Regístrelo de la misma manera:

builder.Services.AddHostedService<GrainInitializerService>();

Orleans" Tareas de inicio

Nota

Aunque todavía se admiten las tareas de inicio, se recomienda usar BackgroundService o IHostedService en su lugar, ya que son el mecanismo de hospedaje de .NET común para ejecutar tareas en segundo plano.

Advertencia

Las excepciones producidas desde una tarea de arranque se notificarán en el registro del silo y provocarán que el silo se detenga. Este enfoque de falla rápida ayuda a detectar problemas de configuración y arranque durante las pruebas en lugar de que causen problemas inesperados más adelante, pero también puede significar que los errores transitorios en una tarea de inicio provocarán la inaccesibilidad del host.

Si necesita usar el sistema de tareas de inicio integrado, puede configurarlos de la siguiente manera:

Registro de un delegado

Un delegado se puede registrar como una tarea de inicio mediante el método de extensión AddStartupTask adecuado en ISiloBuilder.

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

Registro de una implementación de IStartupTask

La interfaz IStartupTask se puede implementar y registrar como tarea de inicio mediante el método de extensión AddStartupTask en 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();
    }
}

Registre la tarea de inicio de la siguiente manera:

siloBuilder.AddStartupTask<CallGrainStartupTask>();