Projelerimizde olağan akışında ilerlerken veya bir business rule çalışırken mevcut akışı durdurmadan asenkron bir şekilde uygulamadan bağımsız çalışmasını istediğimiz process'ler olmuştur. Bu gibi ihtiyaçları karşılaması için Azure olsun Google-Cloud yada Amazon olsun kendi cloud çözümlerini üreterek kullanmamıza olanak sağlamaktadırlar.
Peki ya on-premise dediğimiz kurum içi yada domain içi çözüm olarak neler yapabiliriz ? Fire-and-forget (messaging queue) yapılarından birini kullanabilir veya mevcut uygulamada background job'lar üretebiliriz.
Bu yazımızda Asp.net Core uygulamalarında Hangfire kullanarak background-task'lar nasıl oluşturulur inceleyeceğiz.
Hangfire
Özetle; open-source olarak geliştirilmiş schedule edilebilen process'lerin kolay bir şekilde yönetimini sağlayan bir kütüphanedir. Sahip olduğu dashboard ile job'larınızı historical olarak görüntüleyebilir, start-stop/restart gibi işlemler yapabilirsiniz.
An easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required.
Hangfire job'ları yönetirken storage alanı olarak hemen hemen bütün database türleri için destek sağlamaktadır. SQL Server, Redis, PostgreSQL, MongoDB etc.
İlk olarak uygulamamızda kullanmak üzere local Sql Server üzerinde Hangfire adında bir databse oluşturalım.
Sonrasında Vs.'da BackgroundTaskWithHangfire adında bir Api projesi oluşturalım ve nuget üzerinden bugün için en güncel olan Hangfire v1.6.20 paketini projemize ekleyelim.
PM> Install-Package Hangfire
İlk başta oluşturduğumuz database'in conn string bilgilerini appSettings.json dosyasına ekleyelim.
"HangfireDbConn": "Server=.;Initial Catalog=Hangfire;Persist Security Info=False;User ID=HangfireUser;Password=qwerty135*;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;"
Sırada uygulama üzerinde hangfire configuration'ı var. Bunun için Startup.cs de bulunan ConfigureServices metodu içerisinde Hangfire'ı service olarak ekleyelim ve sonrasında Configure metodu içerisinde bu service'i kullanacağımızı belirten kod bloklarını yazalım.
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(_ => _.UseSqlServerStorage(Configuration.GetValue<string>("HangfireDbConn")));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHangfireDashboard();
app.UseHangfireServer();
}
Yukarıdaki kod bloğunda hangfire storage bilgisini vererek uygulamamız service'lerine register ettik ve devamındada hangfire'ın server ve dashboard service'lerini kullanacağımızı belirttik.
Hangfire dashboard default olarak uygulamanın çalıştığı portta' http://<application>/hangfire adresinde host edilir. Bizde localhostta çalıştığımızdan uygulamayı run edip browser üzerinden http://localhost/hangfire adresine gittiğimizde aşağıdaki gibi hangfire dashboard'u görüntüleyebiliriz.
Dashboard'la birlikte uygulama her start olduğunda db'de ilgili tablolar oluşmuşmu diye check ederek oluşmadıysa tabloları oluşturur. Hangfire tablolarını sql server management studio üzerinden görüntüleyebilirsiniz.
Hangfire konfigurasyonunu tamamladık şimdi sırasıyla Hangfire kütüphanesinde bulunan BackgroundJob sınıfını kullanarak oluşturabileceğimiz job türlerine bakacak olursak;
1- Fire-and-Forget Jobs
Job create edildikten sonra çalışır ve process olur.
public class FireAndForgetJob
{
public FireAndForgetJob()
{
//Fire and forget
var jobId = BackgroundJob.Enqueue(() => ProcessFireAndForgetJob());
}
public void ProcessFireAndForgetJob()
{
Console.WriteLine("I am a Fire and Forget Job !!");
}
}
2- Delayed Jobs
Belli bir zaman bilgisi set edilerek sadece bir kez çalışmasını istediğimiz task'lar için kullanabileceğimiz job türü. Aşağıdaki gibi Job register olduktan 4 dkka sonra çalışacaktır.
public class DelayedJob
{
public DelayedJob()
{
//Delayed job
var jobId = BackgroundJob.Schedule(() => ProcessDelayedJob(), TimeSpan.FromMinutes(4));
}
public void ProcessDelayedJob()
{
Console.WriteLine("I am a Delayed Job !!");
}
}
3- Recurring Jobs
Recurring yani tekrar eden task'lar için kullanılan job türü. Örneğin; her saat başı çalışmasını istediğiniz bir job'a ihtiyacınız olduğunda aşağıdaki gibi tanımlayabiliriz.
public class Recurring_Job
{
public Recurring_Job()
{
//Recurring job
RecurringJob.AddOrUpdate(() => ProcessRecurringJob(), Cron.Hourly);
}
public void ProcessRecurringJob()
{
Console.WriteLine("I am a Recurring Job !!");
}
}
4- Continuations Jobs
Parent-child ilişkisinin olduğu yani bir job'ın çalışması için başka bir job'ın tamamlanmasını bekleyip o Cmplete olduktan sonra çalışmasını istediğimiz işler için kullanabileceğimiz job türü.
public class ContinuationsJob
{
public ContinuationsJob()
{
//Delayed job
var parentJobId = BackgroundJob.Schedule(() => Console.WriteLine("I am a Delayed Job !!"), TimeSpan.FromMinutes(4));
//Continuations job
BackgroundJob.ContinueWith(parentJobId, () => ProcessContinuationsJob());
}
public void ProcessContinuationsJob()
{
Console.WriteLine("I am a Recurring Job !!");
}
}
Projeyi run edip tekrardan http://localhost/hangfire adresine gittiğimizde ilgili job türlerine ait bilgileri dashboard'da görüntüleyebiliriz.
Özetlemek gerekirse; uygulamanızda çalıştırmanız gereken background-task'ları için Hangfire implementasyonunu hızlı bir şekilde yapıp dashboard'u ile birlikte kolayca kullanabilirsiniz. Eğer .net core'un kendi background task sınıfını kullanarak ilerlemek isterseniz hangfire'a göre daha zorlu bir süreç sizi bekliyor olacaktır. Hem yönetilebilirlik açısından hemde visualization olarak hangfire kesinlikle sizin için daha sorunsuz ve kullanışlı bir çözüm olacaktır. Hangfire'ın muadili olan Quartz.net veya bir queue çözümü de kullanarak işlemlerinizi yapabilirsiniz.
Source Code