需求描述

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

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

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

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

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

NET平台定时任务

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

与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运行程序,打开输出视图,看到如下内容

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

    可以看到数据库中增加了不少以HangFire起头的表,这些表就是Hangfire相关持久化生成的表。

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

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

参考:

Hangfire项目实践分享

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

MVC中使用Hangfire执行定时任务的更多相关文章

  1. AspNet MVC中使用Hangfire执行定时任务

    Hangfire在Aspnet中执行定时任务: 第一步: NuGet中加入Hangfire包 第二步: 添加Owin的自启动 第三步.Hangfire的后台控制仪表盘默认情况下只能本地访问,外网访问需 ...

  2. SpringBoot中使用Scheduling执行定时任务

    SpringBoot自带的 Schedule,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多 以下任务都是在单线程下执行的 第一步 创建SpringBoot项目 第二步 外汇 ...

  3. MVC中使用Hangfire按秒执行任务

    更新Hangfire版本到1.7.0,才支持使用按秒循环任务执行 RecurringJob.AddOrUpdate("test",()=>writeLog("每20 ...

  4. MVC中Action的执行过程

    接着上一篇:MVC控制器的激活过程 一.代码现行,该伪代码大致解析了Action的执行的过程 try { Run each IAuthorizationFilter's OnAuthorization ...

  5. Spring Mvc中使用Task实现定时任务,以及遇到的一个问题

    Spring中实现定时任务其实很简单,可以使用spring中自带的task 相当于轻量级的Quartz,并且spring 3.0 之后支持注解的方式,使用起来非常简单,方便,具体实现如下: 第一步,修 ...

  6. mvc中使用Hangfire处理后台任务

    考虑下如下代码,在数据保存后,需要发送邮件,发送邮件是个耗时的工作. 我们的目的是,数据保存成功后,就可以返回响应了,发送邮件不重要,不需要等待邮件发送成功 [HttpPost] public Act ...

  7. MVC中Action参数绑定的过程

    一.题外话 上一篇:MVC中Action的执行过程 ControllerContext 封装有了与指定的 RouteBase 和 ControllerBase 实例匹配的 HTTP 请求的信息. 二. ...

  8. 白话学习MVC(八)Action的执行二

    一.概述 上篇博文<白话学习MVC(七)Action的执行一>介绍了ASP.NET MVC中Action的执行的简要流程,并且对TempData的运行机制进行了详细的分析,本篇来分析上一篇 ...

  9. MVC中权限的知识点及具体实现代码

    一:知识点部分 权限是做网页经常要涉及到的一个知识点,在使用MVC做权限设计时需要先了解以下知识: MVC中Url的执行是按照Controller->Action->View页面,但是我们 ...

随机推荐

  1. google thumbnailator

    Thumbnailator 是一个优秀的图片处理的Google开源Java类库.处理效果远比Java API的好. 从API提供现有的图像文件和图像对象的类中简化了处理过程,两三行代码就能够从现有图片 ...

  2. Java中的NIO及IO

    1.概述 Java NIO(New IO) 是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同, ...

  3. css设置超出部分文档隐藏(在table标签中不好使解决方案在下)

    css设置: .text-over{overflow: hidden;white-space: nowrap;text-overflow: ellipsis;cursor: pointer} div设 ...

  4. PHP在win7安装Phalcon框架

    我的环境是64位的 Win7. 安装 Phalcon 也极其简单,只需要下载一个文件(php_phalcon.dll), 要以 phpinfo() 里面“Architecture”属性为准! 下载地址 ...

  5. inux中Vi不能高亮显示行号的解决办法

    适用版本:CentOS,RedHat,UBUNTU,Fedora解决办法如下: 在UBUNTU中vim的配置文件存放在/etc/vim目录中,配置文件名为vimrc 在Fedora中vim的配置文件存 ...

  6. <td> 行高多层设置的问题

    在一个table中,设置了class,并且对应的样式设置了td的高度时,在其嵌套的table中的td高度不能设置大于父table的td的高度. 只有一种方法可以设置,如下: <table wid ...

  7. IIS 6 备忘

    用IIS7久了, 回到IIS6 总被搞混,所以记录下,以备忘记. 以下是转载和整合了他人的资源,原出处不详.   IIS Web 服务器的权限设置有两个地方,一个是 NTFS 文件系统本身的权限设置, ...

  8. Devexpress VCL Build v2014 vol 14.2.5 发布

    和xe8 几乎同一天出来,但是目前官方不支持xe8. The following sections list all minor and major changes in DevExpress VCL ...

  9. java中配置自定义拦截器中exclude-mapping path是什么意思?

    <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/>//过滤全部请求 & ...

  10. gj10 python socket编程

    10.1 HTTP.Socket.TCP这几个概念 五层网络模型 socket 不属于任何协议,是一个API,通过socket 可以和传输层的打交道,然后在之上可以实现自己的功能和协议 10.2 cl ...