前段時間,花了大量的時間,將原先的計劃任務,切換到Quartz.NET來進行管理。原先的後台定時服務都是通過計劃任務來實現的,但是隨著業務增長,計劃任務也越來越多,每個後台服務,都得創建一個計劃任務。日常的維護和管理非常麻煩。
於是乎,一咬牙,決定引入Quartz.NET框架,統一都管理全部的後台定時服務。
Quartz.NET的優點和使用場景,這裡不再多說,網上有很多說明,總的來說就是,Quartz.NET是一個開源的作業調度框架,非常適合在平時的工作中,定時輪詢數據庫同步,定時郵件通知,定時處理數據等。 Quartz.NET允許開發人員根據時間間隔(或天)來調度作業。它實現了作業和觸發器的多對多關系,還能把多個作業與不同的觸發器關聯,配置靈活方便。
參考官方學習文檔:http://www.quartz-scheduler.net/documentation/index.html
快速搭建一個Quartz,源代碼下載
第一步:新建解決方案和相關項目,並安裝相關程序包,如下圖所示:
Quartz依賴Common.Logging和Common.Logging.Log4Net,而且Log4Net也是比較熟悉的日志工具,因此我們實際使用中,也是log4net記錄日志,另外定時作業一般都是在window服務中,我們也可用Topshelf來創建我們的window服務。
第二步:創建兩個Job類DemoJob1,DemoJob2。實現IJob,在Execute方法裡編寫要處理的業務邏輯,系統就會按照Quartz的配置,定時處理。
using System;
namespace Quartz.Net.Jobs
{
/// <summary>
/// 實現IJob接口
/// </summary>
public class DemoJob1 : IJob
{
private static readonly Common.Logging.ILog logger = Common.Logging.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void Execute(IJobExecutionContext context)
{
try
{
logger.Info("DemoJob1 任務開始運行");
for (int i = 0; i < 10; i++)
{
logger.InfoFormat("DemoJob1 正在運行{0}", i);
}
logger.Info("DemoJob1任務運行結束");
}
catch (Exception ex)
{
logger.Error("DemoJob2 運行異常", ex);
}
}
}
}
第三步:配置quartz.config、quartz_jobs.xml
quartz.config
# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedence
quartz.scheduler.instanceName = QuartzTest
# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal
# job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
# export this server to remoting context
#quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
#quartz.scheduler.exporter.port = 555
#quartz.scheduler.exporter.bindName = QuartzScheduler
#quartz.scheduler.exporter.channelType = tcp
#quartz.scheduler.exporter.channelName = httpQuartz
quartz_jobs.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file contains job definitions in schema version 2.0 format -->
<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>
<!--定義示例任務1 Job-->
<job>
<name>DemoJob1</name>
<group>DeomJobGroup</group>
<description>Quartz.Net示例任務1</description>
<job-type>Quartz.Net.Jobs.DemoJob1,Quartz.Net.Jobs</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<!--定義示例任務2 Job-->
<job>
<name>DemoJob2</name>
<group>DeomJobGroup</group>
<description>Quartz.Net示例任務2</description>
<job-type>Quartz.Net.Jobs.DemoJob2,Quartz.Net.Jobs</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<!--定義示例任務1 觸發器 每30秒執行一次DemoJob1任務-->
<trigger>
<cron>
<name>DemoJob1Trigger</name>
<group>DeomJobTriggerGroup</group>
<job-name>DemoJob1</job-name>
<job-group>DeomJobGroup</job-group>
<cron-expression>0/30 * * * * ?</cron-expression>
</cron>
</trigger>
<!--定義示例任務2 觸發器 每分鐘執行一次DemoJob2任務-->
<trigger>
<cron>
<name>DemoJob2Trigger1</name>
<group>DeomJobTriggerGroup</group>
<job-name>DemoJob2</job-name>
<job-group>DeomJobGroup</job-group>
<cron-expression>0 * * * * ?</cron-expression>
</cron>
</trigger>
<!--定義示例任務2 觸發器 每天凌晨01:00執行一次DemoJob2任務-->
<trigger>
<cron>
<name>DemoJob2Trigger2</name>
<group>DeomJobTriggerGroup</group>
<job-name>DemoJob2</job-name>
<job-group>DeomJobGroup</job-group>
<cron-expression>0 0 1 * * ?</cron-expression>
</cron>
</trigger>
</schedule>
</job-scheduling-data>
第四步:宿主程序,可以是window服務,也可以是後台Console程序,如何用Topshelf來創建我們的window服務,請看另外一篇文章《使用Topshelf 開發windows服務》。
namespace Quartz.Net.Console
{
class Program
{
private static IScheduler scheduler;
static void Main(string[] args)
{
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
scheduler = schedulerFactory.GetScheduler();
scheduler.Start();
}
}
}
運行後,效果如下圖: