Hangfire 是什么?

Hangfire 是一个定时任务的管理后台,它拥有定时任务功能和及其相关的管理后台界面。Hangfire 原生使用 .NET 开发的,同时支持 .NET.NET Core 框架,所以可同时运行在 Windows 和 非 windows 平台上。

Hangfire 可以做什么?

其实上面已经提到了,可以像 Quartz.NET 一样自定义定时任务,但 Hangfire 提供了任务的 Web 管理界面,所以你可以很方便的查看任务状态管理任务,你也不需要远程登录 Windows Server 桌面重启或停止任务了,方便了很多,同时它提供持久化,即使程序挂掉或重启,上次未被执行或没执行完成的任务会继续执行。

是不是有点小期待,想知道 Hangfire 怎么用,别急下面就介绍如何使用,如果你一点都不期待,你也可以稍微花些许时间看一眼,没准也许你会不经意喜欢上它。好了,废话不说了,重点马上来!

Hangfire 如何使用?

这次我打算依旧使用 ASP .NET Core 作为本次的例子开发框架,例子代码地址会放在文章最后。在终端输入以下代码创建项目:

mkdir ~/Development/HangfireJobs && cd ~/Development/HangfireJobs
dotnet new sln
dotnet new mvc -n HangfireJobsApp
dotnet sln add ./HangfireJobsApp/HangfireJobsApp.csproj
cd ./HangfireJobsApp
dotnet restore
dotnet build
dotnet run
...

现在一个基本的 Asp .Net Core MVC 项目在你本地创建并运行起来了,如下图所示:



接下来在终端输入以下代码,来添加Hangfire相关的包

dotnet add package HangFire --version 1.6.19
dotnet add package HangFire.Redis.StackExchange --version 1.7.2
dotnet build

这里任务持久化使用 Redis,所以添加了 HangFire.Redis.StackExchange nuget包,这是个三方的不是原作者开发的,原生的 Redis 包需要商业收费,但我觉得这个包暂时够用了。接下来,使用 VSCode 打开 Startup.cs 文件,敲入写入以下代码:

public void ConfigureServices(IServiceCollection services)
{
// 自动生成代码忽略 // 注入Hangfire
services.AddHangfire(cfg=>{
cfg.UseRedisStorage(Configuration.GetConnectionString("Hangfire"));
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// 自动生成代码忽略 // 启用Hangfire
app.UseHangfireServer();
app.UseHangfireDashboard();
}

最后在appsettings.json文件,加入以下配置:

{
// ... "ConnectionStrings":{
"Hangfire":"127.0.0.1:6379"
}
}

因为持久化用 Redis,所以这里需要你配置 Redis 地址,那么运行你的项目,然后在浏览器上输入地址



到这里,你已经完成了大部分工作,剩下的就是实现具体任务啦。

不过别急,我们先看看 Hangfire 的任务类型。

Hangfire有三种类型的任务:FAF(fire adn forget)即一次性任务,计划任务(在某个时间点执行一次),还有就是最常用的周期性任务,可以设置某个时刻重复执行。还是用代码展示吧。

...
// 立即执行的单次任务
BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));
// 创建计划任务,5分钟后执行
BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromMinutes(5));
// 创建周期性任务,每隔2分钟执行一次
RecurringJob.AddOrUpdate("JobA", () => Console.WriteLine("Recurred"), Cron.MinuteInterval(2));
// 创建周期性任务,每天21:10执行,
RecurringJob.AddOrUpdate("JobB", () => Console.WriteLine(DateTimeOffset.Now), "10 21 * * *");
// 创建周期性任务,每天21:10执行
RecurringJob.AddOrUpdate("JobC", () => Test(), "10 21 * * *", TimeZoneInfo.Local);
...
public void Test()
{
Console.WriteLine(DateTimeOffset.Now);
}

在代码里,你发现周期任务我多列了2个,而且貌似执行时间都相同,然而还是不同的。你需要注意时区的问题,Recurring 添加任务时默认是UTC-0时区,所以当你写代码创建任务时,要注意是否需要指定时区,否则任务可能不会按照你预期的时间执行。

其实这段代码,还有些东西需要注意,也许你注意到了,就是在控制台输出的时间,在最后两个任务是不一致的,你或许会说是因为时区问题,即使改成同一时区输出结果也还是不同,你可以想想为什么。

JobActivator

上面的创建任务的例子确实有些简单了,你想要更优雅的创建任务,比如通过依赖注入的方式。别急 Hangfire 已经提供了解决方法,没错就是 JobActivator,它允许你通过依赖注入这样更方便的方式调用你自定义的任务。

在这个例子里,我分别创建三个类:HFSimpleJob,HFJobActivator,HFJobActivatorScope,代码如下:

// HFSimpleJob.cs
...
public class HFSimpleJob
{
int counter = 0;
public void Run()
{
counter++;
Console.WriteLine($"当前时间是:{DateTimeOffset.Now},当前计数:{counter}");
}
}
// HFJobActivator.cs
...
public class HFJobActivator : JobActivator
{
readonly IServiceScopeFactory _serviceScopeFactory;
public HFJobActivator(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public override JobActivatorScope BeginScope(JobActivatorContext context)
{
return new HFJobActivatorScope(_serviceScopeFactory.CreateScope());
}
}
// HFJobActivatorScope.cs
public class HFJobActivatorScope : JobActivatorScope
{
IServiceScope _serviceScope;
public HFJobActivatorScope(IServiceScope serviceScope)
{
if (serviceScope == null) throw new ArgumentNullException(nameof(serviceScope));
_serviceScope = serviceScope;
}
public override object Resolve(Type type)
{
return _serviceScope.ServiceProvider.GetService(type);
}
public override void DisposeScope()
{
_serviceScope.Dispose();
}
}

HFSimpleJob就是一个简单的模拟业务的任务类,就不细说了,重点说说后面两个。HFJobActivator这个类继承自 JobActivator ,它用来在任务执行前实例化你注入的任务类的 Activator,而 HFJobActivatorScope 继承自 JobActivatorScope,这个类的作用就是调用 IOC 容器实例化之前注入的类。

OK,现在再加上如下代码:

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<HFSimpleJob>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
.... // 添加自定义依赖注入相关类
GlobalConfiguration.Configuration.UseActivator(new HFJobActivato(serviceProvider.GetService<IServiceScopeFactory>()));
// 启用Hangfire
app.UseHangfireServer();
app.UseHangfireDashboard(); // 依赖注入
RecurringJob.AddOrUpdate<HFSimpleJob>("JobIOCA", p => p.Run(), "*/2 * * **");
}

编译运行代码,就可以看到类似下面截图的内容了,最后一个就是使用依赖注入的方式创建的任务:



是不是觉得这样写,没感觉简单多少,这里只是简单举例讲述怎么用,需要自己具体问题具体分析。我这里写一个我的用例,我先定义任务接口,然后所有的业务任务类都实现这个接口,然后使用反射将这些类通过 IOC 的方式批量注入,这样后面新增其它业务的任务,就无须关注业务以外的任务注册调用的代码了,只要实现那个接口测试编译通过即可,这样就简单了很多。这里就不写怎么实现了,你可以自己想想如何,我会把这部分功能放在Demo里。

Hangfire初探的更多相关文章

  1. 开源的.NET定时任务组件Hangfire解析

    项目慢慢就要开工了,很多园友都在问这个事情,看来大伙对这事很上心啊,事情需要一步步的来,尽量写出一个我们都满意的项目.以前每次在博客前面都会扯淡一下,不过很多人都抱怨这样做不好,加上我这人扯淡起来就停 ...

  2. NET定时任务组件Hangfire

    开源的.NET定时任务组件Hangfire解析 项目慢慢就要开工了,很多园友都在问这个事情,看来大伙对这事很上心啊,事情需要一步步的来,尽量写出一个我们都满意的项目.以前每次在博客前面都会扯淡一下,不 ...

  3. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  4. ABP文档 - Hangfire 集成

    文档目录 本节内容: 简介 集成 Hangfire 面板授权 简介 Hangfire是一个综合的后台作业管理器,可以在ABP里集成它替代默认的后台作业管理器,你可以为Hangfire使用相同的后台作业 ...

  5. 初探领域驱动设计(2)Repository在DDD中的应用

    概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...

  6. CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探

    CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...

  7. ABP源码分析三十九:ABP.Hangfire

    ABP对HangFire的集成主要是通过实现IBackgroundJobManager接口的HangfireBackgroundJobManager类完成的. HangfireBackgroundJo ...

  8. 从273二手车的M站点初探js模块化编程

    前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数 ...

  9. JavaScript学习(一) —— 环境搭建与JavaScript初探

    1.开发环境搭建 本系列教程的开发工具,我们采用HBuilder. 可以去网上下载最新的版本,然后解压一下就能直接用了.学习JavaScript,环境搭建是非常简单的,或者说,只要你有一个浏览器,一个 ...

随机推荐

  1. bzoj2331 [SCOI2011]地板

    Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板.现在小L想知道,用 ...

  2. Python解析配置文件模块:ConfigPhaser

    算是前几周落下的博客补一篇.介绍一下python中如何解析配置文件.配置文件常用的几种格式:xml,json,还有ini.其中ini算是最简单的一种格式,因为小,解析的速度也要比xml和json快(并 ...

  3. AWESOME SWIFT-swift.libhunt.com-swift类库网站

    https://swift.libhunt.com/categories/688-events 29 Events libraries and projects ORDERED BY POPULARI ...

  4. HDU 1281 棋盘游戏 【二分图最大匹配】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1281 题意概括: 有N*M大的棋盘,要在里面放尽量多的“车”,求最多能放的车的个数,和为了放最多的车有多 ...

  5. ASP.NET Web API编程——文件下载

    断点续传基本原理 HTTP协议中与断点续传相关的HTTP头为:Range和Content-Range标头,断点续传实现流程: 1)客户端请求下载一个文件,文件的总长度为n:已经下载了一部分文件,长度为 ...

  6. jenkins没安装git报错

    Jenkins新建项目中源码管理使用Git时遇到如下问题: 在安装jenkins服务器上查看一下git版本,可能没有安装git  也可能是git版本太低 [root@localhost nnnnn]# ...

  7. POJ 1328 Radar Installation(很新颖的贪心,区间贪心)

    Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 106491   Accepted: 2 ...

  8. C++备忘知识整理

    一.设置字体颜色 C++控制台程序运行时输出框默认的文字颜色是白色,所以我常称其输出框为黑白框.但是这个文字样式不是固定不变的,是可以改变颜色的字体的.方法有两种: 1.设置输出框的框体属性.在运行时 ...

  9. 修改office文档修改日期

    修改“创建日期”可采用如下方法: 首先把系统日期调整到您所希望的时间,然后到MS-DOS方式下,对该文件输入如下命令:COPY /B filename +,, (一个加号.两个逗号),当询问您是否确认 ...

  10. ssm框架基础搭建

    1项目搭建环境  windows10+eclipse4.8+tomcat7+jdk1.7 2.使用maven搭建 1)首先eclipse配置好maven环境 2)file--new--other 3) ...