Skocz do zawartości

Czasochłonne operacje w ASP.NET – Hangfire


Recommended Posts

Napisano

W jednym z poprzednich wpisów, pokazałem jak prawidłowo tworzyć wątki w tle w celu wykonania jakieś czasochłonnej operacji w ASP.NET. Pod wpisem, Michal Dymel zaproponował narzędzie o nazwie Hangfire.
Muszę przyznać, że framework jest bardzo prosty w użyciu i nie ma zbyt wiele zewnętrznych zależności. Od kilku tygodni korzystam z niego w jednym ze swoich projektów i nie miałem żadnych problemów z konfiguracją czy wdrążaniem rozwiązania w system produkcyjny.

Po kolei jednak… Hangfire służy do wykonywania czasochłonnych operacji w ASP.NET. Dostarcza zatem model “fire&forget”, czyli bardzo prostą implementację systemu kolejkowego. Jeśli zaplanowane zadanie niepowiedzie się (np. timeout), wtedy zostanie automatycznie kilkakrotnie razy powtarzane, w różnych odstępach czasu (tak jak w nServiceBus).
Wiemy, że IIS może zamknąć proces w dowolnym momencie, kończąc tym samym wszystkie zadania, które były wykonywane w tle. Dzięki Hangfire, nie musimy się martwić o wznawianie takiej operacji.

Zaplanowane zadania, przechowywane są w bazie danych, np. SQL Server czy Redis. Istnieje możliwość zaimplementowania własnego repozytorium, ale jest to dość skomplikowane.

Ponadto, Hangfire dostarcza bardzo przyjazny interfejs użytkownika. Instalacja jest bardzo prosta – wystarczy zainstalować poniższy pakiet NuGet:

 Install-Package HangFire

Następnie w Owin startup, umieszczamy:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            GlobalConfiguration.Configuration
              .UseSqlServerStorage(@"Server=PIOTR\SQLEXPRESS;Database=HangfireDb;Trusted_Connection=True;");

            app.UseHangfireDashboard();
            app.UseHangfireServer();
        }
    }

Powyższy przykład bazuje na SQL Server jako repozytorium zadań. Hangfire sam stworzy wymaganą strukturę tabel. Po uruchomieniu aplikacja, baza danych zostanie zainicjalizowana następującymi tabelami:

hangfiredb

W celu zaplanowania zadania, które wykonuje się o określonym czasie wystarczy:

RecurringJob.AddOrUpdate("Nazwa zadania",() => Console.WriteLine("Zaplanowane zadanie...."),Cron.Minutely);

Zwykle powyższy kod umieszcza się w Startup. Możemy przekazać jako parametr dowolne wyrażenie CRON. Hangfire zadba, aby zadanie wykonywało się o określonych porach oraz zostało wznawiane w przypadku recycling dokonywanego przez IIS.

Możemy również dodać zadanie do kolejki,  jeśli chcemy, aby zostało wykonane tylko raz:

BackgroundJob.Enqueue(
    () => Console.WriteLine("Test"));

Dużym udogodnieniem jest dostarczenie UI w formie dashboard. Przechodząc na stronę /hangfire (np. http://localhost:63486/hangfire), zobaczymy diagram pokazujący liczbę wykonanych zadań w ciągu ostatniego tygodnia lub dnia:

dashboard

W zakładce “Recurring tasks” zobaczymy nasze zaplanowane zadania:

recurring_tasks

Mamy szybki i łatwy podgląd, kiedy ostatnio zadanie zostało wykonywane i z jaką częstotliwością będzie wykonywane.

Przechodząc do zakładki Jobs, zobaczymy listę dostępnych kolejek:

queues

Widzimy, że aktualnie mamy 9 zadań w “Succeeded”.  Hangfire zadba o tym, aby nie zapychać powyższych kolejek i każdego dnia niepotrzebne wpisy zostają usuwane. Przechodząc do jakiejkolwiek kolejki, możemy przyjrzeć się szczegółom wykonanemu zadaniowi:

task_sucess

Załóżmy, że nasze zadanie teraz będzie wyrzucało wyjątek:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            GlobalConfiguration.Configuration
                .UseSqlServerStorage(@"Server=PIOTR\SQLEXPRESS;Database=HangfireDb;Trusted_Connection=True;");

            app.UseHangfireDashboard();
            app.UseHangfireServer();

            RecurringJob.AddOrUpdate("Nazwa zadania", () => SampleTask(), Cron.Minutely);
        }

        private static void SampleTask()
        {
            throw new NotImplementedException();
        }
    }

W zakładce Retries zobaczymy wtedy wpis informujący nas, że zadanie nie zostało wykonywane i Hangfire próbuje je wykonywać powtórnie:
retries

Oczywiście po pewnym czasie, gdy próby nie przyniosą efektu, zadanie zostanie na stałe przeniesione do “Failed” (gdzie ręcznie możemy wznowić wykonywanie).

Przechodząc do szczegółów zadania, zobaczymy informacje o wyjątku:

error_details

Ponadto HangFire integruje się z popularnymi loggerami (np. nLog, log4net) i jakiekolwiek logi wykonane przez Hangfire będą widoczne w naszych logach. Nic nie trzeba konfigurować – Hangfire automatycznie wykryje, aktualnie wykorzystywanego w systemie loggera.

Wyświetl pełny artykuł

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...