Hangfire任务调度框架使用
阅读原文时间:2023年07月08日阅读:1

  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的仪表盘

  

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章