다음을 통해 공유


백그라운드 서비스 및 시작 작업

Orleans 애플리케이션을 빌드할 때 애플리케이션이 시작될 때 백그라운드 작업을 수행하거나 구성 요소를 초기화해야 하는 경우가 많습니다.

시작 작업을 사용하여 사일로(실로) 시작 시 초기화 작업 또는 시작 후 요청을 수락하기 전이나 후에 초기화를 수행합니다. 일반적인 사용 사례는 다음과 같습니다.

  • 곡물 상태 초기화 또는 데이터 미리 로드
  • 외부 서비스 연결 설정
  • 데이터베이스 마이그레이션 수행
  • 구성 유효성 검사
  • 캐시 준비

권장되는 방법은 .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 시작 작업

메모

시작 작업도 지원되지만, 백그라운드 작업을 실행하는 표준 .NET 호스팅 메커니즘이므로 BackgroundService 또는 IHostedService을 사용하는 것을 권장합니다.

경고

스타트업 작업에서 보낸 모든 예외는 사일로 로그에 보고되며, 사일로를 중지시킵니다. 이 빠른 실패 방법은 나중에 예기치 않은 문제를 일으키지 않고 테스트 중에 구성 및 부트스트랩 문제를 검색하는 데 도움이 됩니다. 그러나 시작 작업의 일시적인 오류로 인해 호스트를 사용할 수 없게 될 수도 있습니다.

기본 제공 시작 작업 시스템을 사용해야 하는 경우 다음과 같이 구성합니다.

대리자 등록

적절한 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 구현 등록

IStartupTask 인터페이스를 구현하고, AddStartupTaskISiloBuilder 확장 메서드를 사용하여 시작 작업으로 등록합니다.

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