MVC中使用Hangfire执行定时任务

需求描述

项目中有一个通知公告的功能,在后台管理员添加公告后须要推送消息给全部注册用户,让其查看消息。消息推送移动端采用极光推送,可是消息在什么时候发送是个问题,好比说有一个重要的会议通知,可能但愿在会议开始前半天进行提醒,仅仅使用后台代码处理起来可能比较麻烦,这时就须要考虑到使用做业来处理这种定时执行的业务。html

在NET平台,做业有不少方式,能够diy一个系统做业,或者使用数据库的做业功能写一个定时执行,再有一种方案就是使用外部开源的定时任务系统来完成。mysql

首先来讲,采用系统DIY做业的方式。在不一样平台上都有相应的命令来支持这一操做,完成起来也不是很难,可是这样的话应用程序会和系统高耦合,万一想换系统或者换服务器,做业内容直接丢失,再者若是搞很差维护起来也比较麻烦。因此这个pass掉了linux

再者说数据库,各大数据库也都支持做业功能,sql server 或者mysql等。一样面临的问题 第一,不一样数据库命令不一致;第二,添加了做业之后在数据库调整,好比数据库服务迁移会致使做业中断;还有一点,数据库做业若是作定时数据更新,数据库备份是比较不错的选择,都在持久层层面,与业务无关。可是若是牵扯到业务,那就有些麻烦了,想象一下,数据库定时执行了一个邮件发送的任务,生成了一条邮件的记录,而后通知IIS相关进程发送邮件,颇有些本末倒置的感受。git

前二者其实各有各的使用场景,仍是那句话,技术没有好坏,只有适合不适合。针对咱们的业务来讲,发起于应用内,在应用内部解决是比较好的方案。这样就须要第三个方案,集成一个定时任务的系统进来(或者本身写一个,实话说真没写过不知道有大的工做量)。github

NET平台定时任务

net平台开源的定时任务系统也有很多吧,比较知名的有Quartz.net、Hangfire等等。初次使用这些,选择的时候以知足业务的同时简单快速为主,综合看了一下,最后选择Hangfire。一下是摘自园子关于两者区别的部分 :sql

与quartz.net对比

在项目没有引入Hangfire以前,一直使用的是Quartz.net。我的认为Quartz.net在定时任务处理方面优点以下: 数据库

  • 支持秒级单位的定时任务处理,可是Hangfire只能支持分钟及以上的定时任务处理

缘由在于Hangfire用的是开源的NCrontab组件,跟linux上的crontab指令类似。 浏览器

  • 更加复杂的触发器,日历以及任务调度处理服务器

  • 可配置的定时任务并发

可是为何要换Hangfire? 很大的缘由在于项目须要一个后台可监控的应用,不用每次都要从服务器拉取日志查看,在没有ELK的时候至关不方便。Hangfire控制面板不只提供监控,也能够手动的触发执行定时任务。若是在定时任务处理方面没有很高的要求,好比必定要5s定时执行,Hangfire值得拥有。抛开这些,Hangfire优点太明显了:

  • 持久化保存任务、队列、统计信息

  • 重试机制

  • 多语言支持

  • 支持任务取消

  • 支持按指定Job Queue处理任务

  • 服务器端工做线程可控,即job执行并发数控制

  • 分布式部署,支持高可用

  • 良好的扩展性,如支持IOC、Hangfire Dashboard受权控制、Asp.net Core、持久化存储等

说了这么多的优势,咱们能够有个案例,例如秒杀场景:用户下单->订单生成->扣减库存,Hangfire对于这种分布式的应用处理也是适用的,最后会给出实现。

想了解更多参见原文:Hangfire项目实践分享

 

在MVC中使用Hangfire

下文中开发环境为 Vs 2017,Net Framework 4.5+,数据库为sql server 2008 r2 (要求sql server 2008+)

  1. 首先在项目使用nuget引入相关包

    项目上右键,管理Nuget程序包→浏览,输入Hangfire,分别安装Hangfire、Hangfire.core、Hangfire.Sqlserver;

    在安装hangfire时会关联安装owin,若是不想引入Owin的话能够去掉,在注册服务的时候须要单独处理

  2. 右键当前项目,添加OWIN Startup类,在文件中编写代码

    以下

    //指定使用Sqlserver进行定时任务的持久化
                GlobalConfiguration.Configuration.UseSqlServerStorage("DefaultConnection"); //启用服务
     app.UseHangfireServer(); //启用Dashboard面板
                app.UseHangfireDashboard();
  3. 在项目中进入Controller文件夹,在HomeController中添加代码
    public ActionResult Index() { //支持基于队列的任务处理:任务执行不是同步的,而是放到一个持久化队列中,以便立刻把请求控制权返回给调用者。
                var jobId = BackgroundJob.Enqueue(() => WriteLog("队列任务")); //延迟任务执行:不是立刻调用方法,而是设定一个将来时间点再来执行。
                BackgroundJob.Schedule(() => WriteLog("延时任务"), TimeSpan.FromSeconds(10)); //循环任务执行:一行代码添加剧复执行的任务,其内置了常见的时间循环模式,也可基于CRON表达式来设定复杂的模式。
                RecurringJob.AddOrUpdate(() => WriteLog("每分钟执行任务"), Cron.Minutely); //注意最小单位是分钟 //延续性任务执行:相似于.NET中的Task,能够在第一个任务执行完以后紧接着再次执行另外的任务
                BackgroundJob.ContinueWith(jobId, () => WriteLog("连续任务")); return View(); }

    WriteLog方法在控制台输出了一些当前的任务信息,实际业务中能够作不少事情,发邮件提醒、更新数据等等

    public void WriteLog(string msg) { Debug.WriteLine($"Hangfire于{DateTime.Now}执行了任务[{msg}]"); }
  4. F5运行程序,打开输出视图,看到以下内容QQ截图20180129160059

    到此为止,Hangfire就已经可使用了,咱们打开数据库

    image 能够看到数据库中增长了很多以HangFire起头的表,这些表就是Hangfire相关持久化生成的表。

  5. 回到浏览器,在当前浏览地址后输入/hangfire ,访问如下Hangfire的dashboard页面,看一下任务的执行状况

image

image

由于有一个间隔一分钟循环执行的任务,截图这么一会的功夫,就已经执行了11次。在这个页面中,能够把已经执行的任务再次执行,能够查看执行失败的任务。

 

参考:

Hangfire项目实践分享

HangFire任务调度实例(Console和MVC中)及Log4Net日志配置

相关文章
相关标签/搜索