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的仪表盘
最新文章
- 剑指offer六:反转链表
- Android -- 简单的图片浏览器
- MS-sqlserver数据库2008如何转换成2000
- Why does yum return error: [Errno 256] No more mirrors to try ?
- three.js 源代码凝视(七)Math/Euler.js
- 关于solaris中 crontab -e 出现数字0的解决办法
- STM32 AD采样电压计算公式
- 大白话Vue源码系列(03):生成render函数
- 浏览器兼容的JS写法总结
- Windows server 2008R2远程桌面3389端口修改方法技巧
- JavaWeb之商品查看后历史记录代码实现
- Spark-shell错误:Missing Python executable &#39;python&#39;, defaulting to ...
- 深入理解Redis高可用方案-Sentinel
- python的类变量和对象变量[转]
- nginx 隐藏 index.php
- Jmeter(十)检查点
- 随手练——P1141 01迷宫
- sql server查询某年某月有多少天
- KVM源代码阅读--内核版本3.17.4
- Android Toast 使用总结
热门文章
- my41_主从延迟大排查
- Centos 的常用命令总结
- 为什么volatile能保证有序性不能保证原子性
- 记一次SQL Server insert触发器操作
- python3.6.4 scrapy框架from PIL import Image报错 from . import _imaging as core
- OpenGL ES2 缩放移动
- 巧用符号链接迁移 HDFS 数据,业务完全无感知!
- CF1080A Petya and Origami 题解
- LuoguP7259 [COCI2009-2010#3] SORT 题解
- fcntl 加锁模块