另一篇介绍任务调度的文章:.net平台下利用Quartz实现高可用的任务调度
首先官网推荐的是利用SQLSERVER来实现持久化,本文主要记录使用MySql实现持久化,想了解mssql操作的,请看官方中文文档:Hangfire中文文档
首先我们创建一个.NET Core 3.1的Web空项目。

我们需要引用三个DLL,Hangfire官网包,一个是第三方扩展的MySql扩展包

修改配置文件,把mysql连接字符串配置好
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"MySqlServerConStr": "server=127.0.0.1;User ID=root;Password=123456;database=hangfire;charset=utf8mb4;Allow User Variables=true;"
}修改Startup.cs
首先添加注入,把配置项注入一下
private readonly IConfiguration _configuration;
/// <summary>
///配置注入
/// </summary>
/// <param name="configuration">The configuration.</param>
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}修改ConfigureServices方法
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(x => x.UseStorage(new MySqlStorage(_configuration["MySqlServerConStr"],
new MySqlStorageOptions
{
TransactionIsolationLevel = IsolationLevel.ReadCommitted, // 事务隔离级别。默认是读取已提交。
QueuePollInterval = TimeSpan.FromSeconds(15), //- 作业队列轮询间隔。默认值为15秒。
JobExpirationCheckInterval = TimeSpan.FromHours(1), //- 作业到期检查间隔(管理过期记录)。默认值为1小时。
CountersAggregateInterval = TimeSpan.FromMinutes(5), //- 聚合计数器的间隔。默认为5分钟。
PrepareSchemaIfNecessary = true, //- 如果设置为true,则创建数据库表。默认是true。
DashboardJobListLimit = 50000, //- 仪表板作业列表限制。默认值为50000。
TransactionTimeout = TimeSpan.FromMinutes(1), //- 交易超时。默认为1分钟。
TablesPrefix = "Hangfire" //- 数据库中表的前缀。默认为none
}
)));
}将服务加入到管道中,修改Configure方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHangfireServer(); //启动hangfire服务
app.UseHangfireDashboard(); //使用hangfire面板
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}这时候,本地的面板已经可以打开的,我们运行不调试:localhost:5050/hangfire

这时候我们去看我们的数据库,会发现自动生成了很多表

这个面板对我们的job可以删除,所以生产环境的时候,必须加入权限验证
首先我们加入一个过滤器MyDashboardAuthorizationFilter.cs
using Hangfire.Dashboard;
using Microsoft.AspNetCore.Http;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace HangfireWeb
{
public class MyDashboardAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context)
{
var httpContext = context.GetHttpContext();
var header = httpContext.Request.Headers["Authorization"];
if (string.IsNullOrWhiteSpace(header))
{
SetChallengeResponse(httpContext);
return false;
}
var authValues = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(header);
if (!"Basic".Equals(authValues.Scheme, StringComparison.InvariantCultureIgnoreCase))
{
SetChallengeResponse(httpContext);
return false;
}
var parameter = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(authValues.Parameter));
var parts = parameter.Split(':');
if (parts.Length < 2)
{
SetChallengeResponse(httpContext);
return false;
}
var username = parts[0];
var password = parts[1];
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
{
SetChallengeResponse(httpContext);
return false;
}
if (username == "admin" && password == "123456")
{
return true;
}
SetChallengeResponse(httpContext);
return false;
}
private void SetChallengeResponse(HttpContext httpContext)
{
httpContext.Response.StatusCode = 401;
httpContext.Response.Headers.Append("WWW-Authenticate", "Basic realm=\"Hangfire Dashboard\"");
httpContext.Response.WriteAsync("Authentication is required.");
}
}
}然后我修改startup.cs管道:将app.UseHangfireDashboard(); 改一下
app.UseHangfireDashboard("/hangfire", new Hangfire.DashboardOptions
{
Authorization = new[] { new MyDashboardAuthorizationFilter() }
});然后刷新我们的localhost:5050/hangfire,就会看到输入账户密码的弹框,账户密码就是我们过滤器中写死的,生产环境中可以读取数据库。
到此,我们的基本搭建都完成了,接下来我们正式开始介绍如何使用Hangfire
首先介绍一下,Hangfire有四种基本的用法。
-Fire-and-forget:任务队列,很多任务都加入队列,任务会被依次执行。Hangfire默认是加入default队列,你也可以配置多个队列。
-Delayed:延迟任务,会在指定时间之后执行。
-Recurring:周期任务,支持corn表达式,指定时间循环执行(用的最多)。
-Continuations:工作流任务,比如第二个任务执行条件,需要第一个任务的执行结果这种。
一、任务队列(Fire-and-forget)
BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));Console.WriteLine("Fire-and-forget")是个方法和参数,你可以直接修改成你的方法和入参即可。
这句代码你写在哪里都可以,写在控制器或者startup类中,只要调用一次,就给队列加入了一次任务。
比如我们创建订单的时候,瞬间好几千万订单量进来,我们入库的动作就可以用这个调度来执行,Hangfire会依次入库。
二、延迟任务(Delayed)
BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromDays(1));比如我们的支付系统,支付完成,通知业务系统支付结果,第一次通知没成功,我可以等待5秒钟,再次通知。
三、周期任务(Recurring)
RecurringJob.AddOrUpdate("job1", () => TaskAction("1"), "0/10 * * * * ?");这个周期任务和我们之前介绍的Quartz几乎效果一样,只是Hangfire调度更加方便,一句代码就可以创建一个周期任务。
比如我们每个月都要发一次通知,我们就可以设置corn表达式,每个月执行一次,然后这句代码只需要在startup类中调用一次,就可以了。
只要我的任务id,就是那个job1,不变,我可以再次用代码更新我的调度程序。非常的方便。
四、工作流任务(Continuations)
var job1= BackgroundJob.Enqueue(() => Console.WriteLine("Hello, "));
BackgroundJob.ContinueWith(job1, () => Console.WriteLine("world!"));大家看以上代码,第一句是一个队列任务,第二句是工作流任务,他在等待第一个任务执行完成。
到这里,我们就讲解完了,我相信如果你认真看完这篇文章,你对Hangfire会有个大概的了解。
川公网安备 51010702003150号
留下您的脚步
最近评论