Hangfire를 사용한 백그라운드 작업 예약

5332 단어

Note: This post is part of C# Advent Calendar 2020.



때로는 요청-응답 모델에서 수행하는 데 너무 많은 시간이 걸리는 작업이 있습니다. 예를 들어 여러 이메일을 보냅니다. 따라서 이메일을 비동기적으로(즉, 백그라운드에서) 보내고 작업이 완료되기 전에 응답을 반환해야 합니다. 아니면 주기적으로 어떤 작업을 수행하고 싶을 수도 있습니다. 예를 들어 자정에 리소스 집약적인 보고서를 생성하거나 고객에게 월별 인보이스를 보냅니다. 즉, 작업을 예약하고 진행 상황을 추적하고 결과를 볼 수 있기를 원합니다.

물론 메모리 내 모델을 사용하고 ASP.NET CoreIHostedService를 사용할 수 있습니다. 그러나 응용 프로그램이 다시 시작되면 예약된 모든 작업이 사라집니다. 따라서 작업이 손실되지 않도록 유지해야 합니다. 그리고 백그라운드 작업을 처리하는 여러 작업자(소비자)가 있고 작업이 다른 시스템에 있을 수 있습니다. 작업이 실패했을 때 재시도하는 것은 어떻습니까?

Hangfire은 이러한 모든 작업을 보다 쉽게 ​​수행할 수 있도록 도와주는 라이브러리입니다. 그것은 매우 인기 있고 잘 테스트되었습니다. 또한 사용자 정의가 가능하며 다양한 종류의 저장 메커니즘을 지원합니다. 또한 백그라운드 작업 처리의 다양한 스타일과 기술을 지원합니다.



행파이어 사용법



ASP.NET Core 앱에서 hangfire를 호스트하고 스토리지에 SQLite를 사용할 것입니다. MSSQL, PostgreSQL, MySQL 및 기타 데이터베이스 엔진을 사용하고 콘솔 앱에서 호스팅할 수도 있습니다. official guide은 매우 좋지만 단계는 다음과 같습니다.


  • 다음 Nuget 패키지*를 추가합니다.

    <PackageReference Include="Hangfire.Core" Version="1.7.18" />
    <PackageReference Include="Hangfire.AspNetCore" Version="1.7.18" />
    <PackageReference Include="Hangfire.Storage.SQLite" Version="0.2.4" />
    
    




  • 종속성 컨테이너에 행파이어 추가:

    // Add Hangfire services.
    services.AddHangfire(configuration => configuration
        .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
        .UseSimpleAssemblyNameTypeSerializer()
        .UseRecommendedSerializerSettings()
        .UseSQLiteStorage());
    
    // Add the processing server as IHostedService
    services.AddHangfireServer();
    
    




  • Hangfire 대시보드 경로 정의:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapHangfireDashboard();
    });
    
    


    이제 앱을 실행하고 /hangfire로 이동하여 볼 수 있습니다. 그러나 아직 일자리가 없습니다.

    작업 대기열에 넣기



    파이어 앤 포겟(fire-and-forget) 방식으로 작업을 대기열에 추가하려면(즉, 결과를 기다리지 않고 정확히 언제 발생할지 크게 신경 쓰지 않음) 다음과 같이 합니다.

    backgroundJobs.Enqueue(() => Console.WriteLine("Hello world from Hangfire!"));
    
    


    일부 종속성이 필요할 수 있는 무언가를 원했다면 어떻게 해야 할까요? 예를 들어 데이터베이스에 연결하거나 구성에 액세스해야 합니까? 그러면 작업에 대한 클래스를 만들고 종속성 주입을 통해 종속성을 얻을 수 있습니다.

    public class SendEmailsJob
    {
        public SendEmailsJob(IConfiguration configuration)
        {
            // You can ask for configuration or any other
            // dependency the job might need via Dependency Injection
        }
    
        [JobDisplayName("Send {0} emails")]
        [AutomaticRetry(Attempts = 3)]
        public async Task Execute(int count)
        {
            for (int i = 0; i < count; i++)
            {
                await Task.Delay(1000);
            }
        }
    }
    
    


    보시다시피 매개변수를 받는 Execute라는 메서드를 정의했습니다. 또한 Hangfire 대시보드에 표시되는 방식 또는 작업이 실패할 경우 Hangfire가 작업을 자동으로 재시도하는 횟수를 제어하는 ​​몇 가지 속성으로 장식했습니다.

    작업을 대기열에 추가하는 방법은 다음과 같습니다.

    _backgroundJobClient.Enqueue<SendEmailsJob>(job => job.Execute(5));
    
    




    예약 작업



    정의된 일정에 따라 작업을 주기적으로 실행하려면 다음과 같이 작성할 수 있습니다.

    Hangfire.RecurringJob.AddOrUpdate<SendEmailsJob>(job => job.Execute(10), cronExpression: "*/5 * * * *");
    
    


    참고: RecurringJob는 정적 클래스입니다.

    작업은 간단한 표현식 또는 클래스가 될 수 있습니다. 그리고 Cron 표현식을 사용하여 일정을 정의합니다. thisthis 과 같은 사이트를 통해 Cron 표현식을 구성할 수 있습니다.

    확장 프로그램



    Hangfire에는 많은 확장 기능이 있습니다here. 그러나 내가 가장 좋아하는 확장 프로그램은 이것입니다. 실시간 로그를 출력할 수 있습니다 :)



    참고: SQLite를 스토리지 엔진으로 사용하는 경우 콘솔은 실시간이 아닙니다.

    소스 코드



    이 문서의 코드와 나머지 ASP.NET Core 앱이 포함된 샘플 애플리케이션here을 넣었습니다.

    좋은 웹페이지 즐겨찾기