開源的.NET定時任務組件Hangfire解析


   項目慢慢就要開工了,很多園友都在問這個事情,看來大伙對這事很上心啊,事情需要一步步的來,盡量寫出一個我們都滿意的項目。以前每次在博客前面都會扯淡一下,不過很多人都抱怨這樣做不好,加上我這人扯淡起來就停不住,有時候還會很感性的說出一些話,所以以后寫博文盡量少扯淡。(如果博文有不足之處,還望多多指正,我也會及時的修改,如果只是單純的刷存在感,說一些過激的話,那我就不怎么高興了)

   項目中很多時候都會使用到定時任務這樣一個功能需求,在.NET中對於完成定時任務的技術還是不怎么多的,.NET Framework具有“內置”定時器功能,通過System.Timers.Timer類。在使用Timer類需要面對的問題:計時器沒有持久化機制;計時器具有不靈活的計划(僅能設置開始時間和重復間隔,沒有基於日期,時間等);計時器不使用線程池(每個定時器一個線程);計時器沒有真正的管理方案 - 你必須編寫自己的機制,以便能夠記住,組織和檢索任務的名稱等。如果需要在.NET實現定時器的功能,可以嘗試使用以下這款開源免費的組件Quartz.Net組件。

  上面介紹了兩種方式,在這里就介紹另外一種組件,那就是Hangfire組件。

一.Hangfire組件概述

    在.NET和.NET Core應用程序中執行后台處理的簡單方法。無需Windows服務或單獨的進程。由持久存儲支持,存儲方式有sqlserver、redis,mongodb等等。Hangfire支持所有類型的后台任務 - 短時間運行和長時間運行,CPU密集型和I / O密集型,一次性和周期性。

   1.組件特點:

   2.組件功能:

      上面是對Hangfire組件背景的一些簡單介紹,下面我們具體來了解一下Hangfire組件的使用方法。

二.Hangfire組件使用方法介紹

      既然想要學習了解一個組件,當然需要知道是怎么樣取使用,如果不能使用,學着也沒有什么很大的用處,下面介紹一下Hangfire組件的一些常用方法。

    1.ASP.NET MVC設置方式:

public void Configuration(IAppBuilder app)
{
    GlobalConfiguration.Configuration.UseSqlServerStorage("<connection string or its name>");
    app.UseHangfireDashboard();
    app.UseHangfireServer();
}

   GlobalConfiguration類是配置Hangfire的首選方式。這是一些方法的入口點,包括來自第三方存儲實現或其他擴展的方法。用法很簡單,只需Hangfire在應用程序初始化類中包含命名空間,並發現GlobalConfiguration.Configuration屬性的擴展方法

   2.控制台設置方式:

 GlobalConfiguration.Configuration
                .UseColouredConsoleLogProvider()               
          .UseSqlServerStorage(
@"Server=.\sqlexpress;Database=Hangfire.Sample;Trusted_Connection=True;") .UseMsmqQueues(@".\Private$\hangfire{0}", "default", "critical");

    3.基於隊列的任務處理:

var jobId = BackgroundJob.Enqueue(
    () => Console.WriteLine("Fire-and-forget!"));

    4.延遲任務執行:

var jobId = BackgroundJob.Schedule(
    () => Console.WriteLine("Delayed!"),
    TimeSpan.FromDays(7));

    5.循環任務執行:

RecurringJob.AddOrUpdate(
    () => Console.WriteLine("Recurring!"),
    Cron.Daily);

    6.繼續在其父作業完成時執行:

BackgroundJob.ContinueWith(
    jobId,
    () => Console.WriteLine("Continuation!"));

    7.批處理方法:

var batchId = BatchJob.StartNew(x =>
{
    x.Enqueue(() => Console.WriteLine("Job 1"));
    x.Enqueue(() => Console.WriteLine("Job 2"));
});

    8.當父批次中的所有后台作業完成時,批處理繼續:

BatchJob.ContinueWith(batchId, x =>
{
    x.Enqueue(() => Console.WriteLine("Last Job"));
});

    9.使用IoC容器:

public  class  ContainerJobActivator  : JobActivator 
{ 
    private  IContainer  _container ;
    public  ContainerJobActivator (IContainer  container )
    { 
        _container  =  container ; 
    }}
    public  override  object  ActivateJob (Type  type )
    { 
        return  _container 。Resolve (type ); 
    } 
}

    在啟動Hangfire服務器之前將其注冊為當前作業啟動器。

var container = new Container();
GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(container));
...
app.UseHangfireServer();

 

      Hangfire將作業保存到持久存儲中,並以可靠的方式處理它們。這意味着你可以中止Hangfire工作線程,卸載應用程序域甚至終止進程,工作將被處理。Hangfire將作業標記為已完成,只有當代碼的最后一行執行,並知道作業可能會失敗,最后一行。它包含不同的自動重試功能,可以處理代碼中的存儲錯誤或錯誤。

三.Hangfire組件核心對象解析

   上面介紹了Hangfire組件的常用方法,Hangfire組件的功能非常多,這里就做介紹了,有興趣可以去官網進行查看api。下面介紹一下Hangfire組件的一些核心對象,初探Hangfire組件深層次的問題。

   1.RecurringJob.AddOrUpdate():

 public static void AddOrUpdate(
            Expression<Action> methodCall,
            string cronExpression,
            TimeZoneInfo timeZone = null,
            string queue = EnqueuedState.DefaultQueue)
        {
            var job = Job.FromExpression(methodCall);
            var id = GetRecurringJobId(job);

            Instance.Value.AddOrUpdate(id, job, cronExpression, timeZone ?? TimeZoneInfo.Utc, queue);
        }

   該方法用於定期作業在指定的CRON計划上觸發多次。該方法具有16個重載,Job.FromExpression(methodCall);用於獲取基於Job類的新實例給定的方法調用的表達式樹。GetRecurringJobId(job)方法根據Job對象獲取對應的JobID。

   2.BackgroundJob.Enqueue():

public static string Enqueue([NotNull, InstantHandle] Expression<Action> methodCall)
        {
            var client = ClientFactory();
            return client.Enqueue(methodCall);
        }

   該方法基於給定的方法調用表達式創建一個新的fire-and-forget作業。該方法接受一個參數,表示將被編組到服務器的方法調用表達式。接下來我們看一下var client = ClientFactory();方法的具體實現

internal static Func<IBackgroundJobClient> ClientFactory
        {
            get
            {
                lock (ClientFactoryLock)
                {
                    return _clientFactory ?? DefaultFactory;
                }
            }
            set
            {
                lock (ClientFactoryLock)
                {
                    _clientFactory = value;
                }
            }
        }

   該屬性定義了一個Func<IBackgroundJobClient>的泛型委托。該屬性是一個可讀可寫的操作,對ClientFactoryLock加鎖,確保不發生死鎖情況。

四.總結

    上面簡單的介紹了Hangfire組件的背景和一些簡單的應用,也着重的介紹了一些對象。這個組件的功能很強大,需要了解的地方也較多,這一篇文章不可能全部介紹,用做拋磚引玉的作用。在這里吐槽一句,微軟最近技術發展太快,很多技術還沒有來得及發展,就有新的技術出來,讓我們這些底層的人着實難受,事物發展有規律,不是以前缺的東西可以在很短的時間就可以補上,還是需要留下足夠的空間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM