另一篇介绍任务调度的文章:.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会有个大概的了解。
留下您的脚步
最近评论