WebAPI中的定時處理-使用Quartz.Net


借鑒:

https://blog.csdn.net/lordwish/article/details/78926252

在最近的一篇文章中講到了如何在web API中實現定時處理,采用的是比較原始的Timer定時器,功能簡單,無法勝任復雜任務。本次就着重介紹一下定時任務框架Quartz.Net。 
Quartz.Net來源於Java中的Quartz框架,后來有了.Net版本就加了后綴.Net以示區別。Quartz.Net可以實現諸如定時發送郵件、定時處理數據、定時輪詢數據庫等計划任務,只需要幾句代碼,不需要Windows計划任務也能實現諸如“每天早上8:00發送郵件”、“每隔半個小時查詢一次庫存”之類的目的。

安裝Quartz.Net

Quartz.Net的安裝可以說非常簡單,使用NuGet管理器是非常方便的。打開Asp.Net項目,我這里用的是WebApi做的例子(當然用MVC、WPF等也是可以的),打開Nuget管理器,查找Quartz.Net,點擊安裝。 
這里寫圖片描述

安裝完成后會發現項目自動添加了三個類庫的引用,分別是Common.Logging、Common.Logging.Core、Quartz,其中Quartz是我們需要用到的核心類庫,其余兩個是日志相關的類庫。

Quartz.Net使用示例

這里我將采用上篇的定時發送郵件的示例來說明Quartz.Net,目標是每半個小時發送一封郵件。

發送郵件方法

        public async Task<int> Auto() { int num = 0; try { MailModel model = new MailModel() { ReceiverAddress = "",//收件人地址 ReceiverName = "",//收件人姓名 Title = "",//郵件標題 Content = "",//郵件內容 SenderAddress = "",//發件人地址 SenderName = "",//發件人姓名 SenderPassword = ""//發件人密碼 }; bool result = MailHelper.SendMail(model); } catch (Exception) { num = -1; } return await Task.FromResult(num); }

創建發送郵件的任務

Quzrtz中有Job的概念,Job就是我們所講的任務。

    using Quartz; using Quartz.Impl; public class TimeJob : IJob { public void Execute(IJobExecutionContext context) { //具體的方法 Auto(); } }

創建類TimeJob並繼承Quzrtz中的接口IJob,實現接口IJob中的方法Execute,在Execute方法中可以創建具體的方法。

創建任務調度器

    public class JobScheduler { public static void Start() { //調度器工廠 ISchedulerFactory factory = new StdSchedulerFactory(); //調度器 IScheduler scheduler = factory.GetScheduler(); scheduler.GetJobGroupNames(); /*-------------計划任務代碼實現------------------*/ //創建任務 IJobDetail job = JobBuilder.Create<TimeJob>().Build(); //創建觸發器 ITrigger trigger = TriggerBuilder.Create().WithIdentity("TimeTrigger", "TimeGroup").WithSimpleSchedule(t => t.WithIntervalInMinutes(30).RepeatForever()).Build(); //添加任務及觸發器至調度器中 scheduler.ScheduleJob(job, trigger); /*-------------計划任務代碼實現------------------*/ //啟動 scheduler.Start(); } }

創建任務調度器類JobScheduler,把上面的定時發送郵件任務TimeJob和觸發器添加到任務調度器中。任務Job就是具體要做的事情,觸發器Trigger就是任務要執行的時機。可以創建多個Job任務和多個Trigger觸發器加入到調度器中。

啟動計划任務

任務調度器已經完成了,下步要做的就是在程序啟動時開啟任務調度器了。在項目的Global.asax.cs中進行如下配置

    public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); //注冊定時任務 Helpers.JobScheduler.Start(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } }

使用配置文件實現計划任務

上面就是一個簡單的定時任務示例,但是還有一點不足之處,那就是觸發器的配置是在代碼中寫的,如果我們想由原來的半個小時發一次改成一個小時發一次,就需要改代碼、編譯、發布,顯然太麻煩,有沒有更好的方式呢?幸運的是Quartz.Net可以通過XML配置文件實現定時任務。仍然是上面發郵件的例子,我們使用配置文件來實現。

修改Web.config文件

修改項目配置文件Web.config,在configSections節點下添加子節點,對應的添加Quartz的基本配置。在最后一行的“key=”quartz.plugin.xml.fileNames” value=”~/quartz_jobs.xml” ”,表示Quertz的任務調度計划。

  <configSections> <!--Quartz--> <section name="quartz" type="System.Configuration.NameValueSectionHandler"/> </configSections> <!--Quartz配置--> <quartz> <add key="quartz.scheduler.instanceName" value="ExampleDefaultQuartzScheduler"/> <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/> <add key="quartz.threadPool.threadCount" value="10"/> <add key="quartz.threadPool.threadPriority" value="2"/> <add key="quartz.jobStore.misfireThreshold" value="60000"/> <add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz"/> <!--******************************Plugin配置*********************************************--> <add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" /> <add key="quartz.plugin.xml.fileNames" value="~/quartz_jobs.xml"/> </quartz>

添加quzrtz_jobs.xml

對應上面提到的配置文件中文件路徑“key=”quartz.plugin.xml.fileNames” value=”~/quartz_jobs.xml” ”,在項目目錄下添加文件quartz_jobs.xml,項目啟動是會從此文件中讀取任務計划來執行,具體內容如下:

<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <!--開始執行一個調度--> <!--任務,可添加多個--> <job> <!--任務名稱【必填】:同一group中多個job的name名不能相同--> <name>TimeJob</name> <!--任務所屬分組【選填】--> <group>Timer</group> <!--任務描述【選填】--> <description>定時任務</description> <!--任務類型【必填】:實現IJob接口完整命名空間的類名,程序集名--> <job-type>WebAPI.Helpers.TimeJob, WebAPI</job-type> <durable>true</durable> <recover>false</recover> </job> <!--觸發器,可添加多個--> <trigger> <!--simple:簡單觸發器類型,cron:復雜觸發器類型【推薦】--> <cron> <!--觸發器名稱【必填】:同一group中多個trigger的name不能相同--> <name>TimeTrigger</name> <!--觸發器組【選填】--> <group>Timer</group> <!--觸發器描述【選填】--> <description>每隔半小時推送未處理報警信息</description> <!--要調度的任務名稱【必填】:必須和對應job節點中的name相同--> <job-name>TimeJob</job-name> <!--要調度的任務的所屬分組【選填】:必須和對應job節點中的group相同--> <job-group>Timer</job-group> <cron-expression>0 */30 * * * ?</cron-expression> </cron> </trigger> <!--結束一個調度--> </schedule> </job-scheduling-data>

修改調度器類

配置文件修改完成后,再對調度器類進行相應修改,只需要將創建任務、觸發器的代碼去掉即可,如下:

    public class JobScheduler { public static void Start() { //調度器工廠 ISchedulerFactory factory = new StdSchedulerFactory(); //調度器 IScheduler scheduler = factory.GetScheduler(); scheduler.GetJobGroupNames(); //啟動 scheduler.Start(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Quartz.Net使用進階

上面就是我們使用Quartz實現的簡單定時任務,如果要實現更復雜的任務調度,強烈推薦使用cron復雜任務觸發器。cron復雜任務觸發器支持使用cron表達式自定義任務調度,理解了cron表達式的結構和用法,實現各種定制性的任務調度就不會有太大問題了。cron表達式由“秒分時日月星期年”共7段構成,其中“年”是可選的。Quartz官方文檔提供的cron表達式的相關說明。

cron表達式說明

字段名 是否必填 取值范圍 允許特殊字符
必填 0-59 ,-*/
必填 0-59 ,-*/
必填 0-23 ,-*/
必填 1-31 ,-*?/LW
必填 1-12或JAN-DEC ,-*/
星期 必填 1-7或SUN-SAT ,-*?/LW
非必填 空,1970-2099 ,-*/

cron特殊字符說明

特殊字符 說明
* 表示“每”,比如每小時、每分鍾、每日、每年
? 表示不指定具體的值,只能出現在日、星期中
- 表示范圍,比如時字段中10-12表示10點、11點、12點
, 表示列舉,比如“MON,WED,FRI”表示周一、周三和周五
/ 表示增量,比如在秒字段中“0/15”表示從0秒開始每次增加15秒,也就是15、30、45秒
L 表示最后的,只能出現在日、星期字段中,表示一個月的最后一天、一個星期的最后一天
W 表示工作日,指距離給定日期最近的工作日
# 表示一個月的第幾個星期幾,比如“6#3”表示每個月的第三個周五

cron表達式示例

表達式 含義
0 0 12 * * ? 每天12點
0 15 10 ? * * 每天10:15
0 15 10 * * ? 每天10:15
0 15 10 * * ? * 每天10:15
0 15 10 * * ? 2005年每天10:15
0 * 14 * * ? 每天14:00到14:59期間的每一分鍾
0 0/5 14 * * ? 每天14:00到14:55期間的每5分鍾
0 0/5 14,18 * * ? 每天14:00到14:55和18:00到18:55期間的每5分鍾
0 0-5 14 * * ? 每天14:00到14:05期間的每一分鍾
0 10,44 14 ? 3 WED 每年三月的星期三的14:10和14:44
0 15 10 ? * MON-FRI 周一到周五的10:15
0 15 10 15 * ? 每月15日的10:15
0 15 10 L * ? 每月最后一天的10:15
0 15 10 L-2 * ? 每月倒數第二天的10:15
0 15 10 ? * 6L 每月最后一個周五的10:15
0 15 10 ? * 6L 2002-2005 從2002年至2005年期間每月最后一個周五的10:15
0 15 10 ? * 6#3 每月第三個周五的10:15
0 0 12 1/5 * ? 從每月第一天開始,每隔5天的12:00
0 11 11 11 11 ? 每年11月11日11:11

Quartz定時任務日志

通過日志記錄定時計划的執行情況是很有用的,Quartz自身提供的Common.Logging來記錄日志,我們也可以結合Log4net或者Nlog來實現定時任務的運行日志,當然也可以保存到數據庫中,具體方法本文不再詳細說明。


以上就是關於Quartz.Net開源計划調度框架的簡單說明,更詳細的內容請參考Quartz的官網

Quartz.Net


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM