Hangfire任務調度框架使用


  1、HangFire簡介

  HangFire是一個免費簡單實用的分布式后台定時調度服務,在現在.net開發中,人氣算是很高的。

  HangFire提供了內置集成化的控制台,可以直觀明了的查看作業調度情況,並且Hangfire不需要依賴於單獨的應用程序執行,支持持久性存儲,默認使用sqlserver。

  2、HangFire安裝

  一般的,我們都是使用nuget安裝HangFire  

    Install-Package Hangfire

  個人不建議這么安裝,最好是根據自己的需求來,因為Hangfire默認使用SqlServer作為存儲數據庫,如果我們使用mysql,就沒有必要了,而且最新的Hangfire會依賴於Hangfire.AspNetCore,方便在.net core項目中使用,本文以mysql作為數據庫來介紹,如果我們用的是.net core項目,安裝

    Install-Package Hangfire.AspNetCore
    Install-Package Hangfire.MySql.Core

  如果是控制台程序,安裝

    Install-Package Hangfire.MySql.Core

  3、HangFire例子

    using Hangfire;
    using Hangfire.MySql.Core;
    using System;
    using System.Threading;
    
    namespace HangFire
    {
        class Program
        {
            static void Main(string[] args)
            {
                //創建表
                var storage = new MySqlStorage("Server=192.168.220.129;port=3306;Database=hangfire;User ID=root;Password=123456;charset=utf8;Allow User Variables=true");
                //使用mysql
                GlobalConfiguration.Configuration.UseStorage(storage);
                
                //添加循環執行的定時任務
                RecurringJob.AddOrUpdate(() => Console.WriteLine("Hangfire  AddOrUpdate任務"), "1/5 * * * * *", TimeZoneInfo.Local, "queue1");
                //后台調度任務
                BackgroundJobServer jobServer = new BackgroundJobServer(new BackgroundJobServerOptions()
                {
                    Queues = new string[] { "queue1", "queue2" },
                    ServerName = "Test",
                    WorkerCount = 1
                }, storage);
                //等待退出
            //jobServer.WaitForShutdownAsync(CancellationToken.None);
    
                Console.ReadLine();
            }
        }
    }

  4、HangFire調度用法

  BackgroundJobServer用於啟動調度,如上面的例子,  

    BackgroundJobServer jobServer = new BackgroundJobServer(new BackgroundJobServerOptions()
    {
        Queues = new string[] { "queue1", "queue2" },
        ServerName = "Test",
        WorkerCount = 1
    }, storage);

  需要注意的是Queues參數,它是BackgroundJobServer會調度的隊列,默認隊列名是default,上面的例子中沒有將default添加到隊列中去,因此所有使用default默認隊列的任務將不會被調度執行,所以建議將default也加進入,即Queues = new string[] { "default", "queue1", "queue2" }。

  重點說的是BackgroundJob和RecurringJob兩個類,這兩個類都是進行調度任務的操作

  BackgroundJob

  BackgroundJob主要用於單次任務的調度

    //添加任務到隊列,會返回任務Id
    BackgroundJob.Enqueue(() => Console.WriteLine("Hangfire  Enqueue任務"));
    //支持異步
    BackgroundJob.Enqueue(() => MyTask.LogAsync());
    //計划執行,即在指定的時間執行
    BackgroundJob.Schedule(() => Console.WriteLine("Hangfire  Schedule任務"), TimeSpan.FromSeconds(10));//延遲10秒后執行
    //支持異步
    BackgroundJob.Schedule(() => MyTask.LogAsync(), TimeSpan.FromSeconds(10));//延遲10秒后執行

  其中MyTask是一個類  

    public class MyTask
    {
        public static async Task LogAsync()
        {
            await Task.Run(() => Console.WriteLine("MyTask"));
        }
    }

  Enqueue用於將任務立即添加到執行隊列等待執行,Schedule用於延遲添加,即延遲指定時間后將任務添加到執行度列。要注意是,這里是添加到默認隊列,也就是default隊列,如果在啟動server時,未添加default隊列,那么將不會被調度執行。而且添加的任務只會被執行一次,另外,這里只是將任務加入到默認隊列中,執行還需要排隊。Enqueue還有一個返回值,即jobId,它表示添加任務得到的任務Id,我們可以通過這個jobId對隊列進行移除,重新進入隊列等等操作。  

    //添加任務到隊列,返回任務Id
    var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Hangfire  Enqueue任務"));
    //指定任務成功執行完再執行,同樣返回新增的任務Id
    var otherJobId = BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Hangfire  ContinueJobWith任務"));
    //移除
    BackgroundJob.Delete(otherJobId);
    //重新進入隊列
    BackgroundJob.Requeue(otherJobId);

  RecurringJob

  RecurringJob主要用於定時循環的任務調度  

    //添加循環執行的定時任務
    RecurringJob.AddOrUpdate(() => Console.WriteLine("Hangfire  AddOrUpdate任務"), "*/5 * * * * *", TimeZoneInfo.Local, "queue1");
    //添加循環執行的定時任務,同時執行recurringJobId
    RecurringJob.AddOrUpdate("myRecurringJobId", () => Console.WriteLine("Hangfire  AddOrUpdate任務"), "*/5 * * * * *", TimeZoneInfo.Local, "queue1");

  這里說下recurringJobId,其實這個就是這個定時任務的名稱,AddOrUpdate就是根據這個recurringJobId來判斷是新增還是更新的,如果不指定recurringJobId,則會自動根據Lambda表達式來生成一個recurringJobId,比如上面會用Console.WriteLine作為recurringJobId,這個recurringJobId還可以用於移除任務和立即觸發:  

    //移除任務
    RecurringJob.RemoveIfExists("myRecurringJobId");
    //立即觸發一次
    RecurringJob.Trigger("myRecurringJobId");

  RecurringJob采用Cron表達式來指明調度時間,這個也是Hangfire的一個優勢。

  另外提一點,BackgroundJob的Enqueue方法和Schedule方法,RecurringJob的AddOrUpdate方法都有一個泛型的重載,上面的例子都是靜態方法,無需調用對象,而這個泛型其實就是任務的調用對象,如:  

    BackgroundJob.Enqueue<TestModel>(tm => tm.Show());

  其中TestModel是  

    public class TestModel
    {
        public string Text { get; set; } = "Test";

        public void Show()
        {
            Console.WriteLine(Text);
        }
    }

  默認情況下,任務的調用實例是JobActivator對象創建的,默認創建方式就是  

    public virtual object ActivateJob(Type jobType)
    {
        return Activator.CreateInstance(jobType);
    }

  因此,這個調用對象必須是有空構造函數,否則,我們需要使用繼承去重寫JobActivator的ActivateJob方法,再使用GlobalConfiguration.Configuration.UseActivator();方法將重寫的JobActivator集成進去,這種方式也可以用於IOC容器的支持。

  5、.net core 使用HangFire

  .net core使用hangfire很簡單,首先安裝Hangfire.AspNetCore和Hangfire.MySql.Core,然后在Startup中集成即可  

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Hangfire.MySql.Core;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.HttpsPolicy;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    namespace Hangfire.Web
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                //添加Hangfire服務
                var storage = new MySqlStorage("Server=192.168.220.129;port=3306;Database=hangfire;User ID=root;Password=123456;charset=utf8;Allow User Variables=true");
                services.AddHangfire(cfg =>
                {
                    cfg.UseStorage(storage);
                });
                //以IHostedService的形式啟動BackgroundJobServer
                //如果這里添加了,那么Configure方法中就無需調用app.UseHangfireServer();
                //services.AddHangfireServer();
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                //配置后台儀表盤
                app.UseHangfireDashboard();
                //開始使用Hangfire服務
                //如果這里添加了中間件,那么ConfigureServices中就無需調用services.AddHangfireServer();
                app.UseHangfireServer();
    
                app.UseHttpsRedirection();
                app.UseMvc();
            }
        }
    }

  然后啟動之后,可以在瀏覽器輸入http://localhost:5000/hangfire打開Hangfire的儀表盤

    

  


免責聲明!

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



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