Quartz.Net调度框架配置解析
在平时的工作中,估计大多数都做过轮询调度的任务,比如定时轮询数据库同步,定时邮件通知等等。大家通过windows计划任务,windows服务等都实现过此类任务,甚至实现过自己的配置定制化的框架。那今天就来介绍个开源的调度框架Quartz.Net(主要介绍配置的实现,因为有朋友问过此类问题)。调度的实现代码很简单,在源码中有大量Demo,这里就略过了。
Quartz.Net当前最新版本Quartz.NET2.0beta1Released
一、基于文件配置
先看一下简单的实现代码
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading;
usingQuartz;
usingQuartz.Impl;
usingCommon.Logging;
namespaceDemo
{
classProgram
{
staticvoidMain(string[]args)
{
//Firstwemustgetareferencetoascheduler
ISchedulerFactorysf=newStdSchedulerFactory();
ISchedulersched=sf.GetScheduler();
sched.Start();
sched.Shutdown(true);
}
}
}
代码很简单,配置文件中的quartz基础配置,以及job,trigger信息是如何加载的?这个过程是发生ISchedulersched=sf.GetScheduler();过程,主要体现在源码这一段
publicvoidInitialize()
{
//short-circuitifalreadyinitialized
if(cfg!=null)
{
return;
}
if(initException!=null)
{
throwinitException;
}
NameValueCollectionprops=(NameValueCollection)ConfigurationManager.GetSection("quartz");
stringrequestedFile=Environment.GetEnvironmentVariable(PropertiesFile);
stringpropFileName=requestedFile!=null&&requestedFile.Trim().Length>0?requestedFile:"~/quartz.config";
//checkforspecials
propFileName=FileUtil.ResolveFile(propFileName);
if(props==null&&File.Exists(propFileName))
{
//filesystem
try
{
PropertiesParserpp=PropertiesParser.ReadFromFileResource(propFileName);
props=pp.UnderlyingProperties;
Log.Info(string.Format("Quartz.NETpropertiesloadedfromconfigurationfile'{0}'",propFileName));
}
catch(Exceptionex)
{
Log.Error("CouldnotloadpropertiesforQuartzfromfile{0}:{1}".FormatInvariant(propFileName,ex.Message),ex);
}
}
if(props==null)
{
//readfromassembly
try
{
PropertiesParserpp=PropertiesParser.ReadFromEmbeddedAssemblyResource("Quartz.quartz.config");
props=pp.UnderlyingProperties;
Log.Info("DefaultQuartz.NETpropertiesloadedfromembeddedresourcefile");
}
catch(Exceptionex)
{
Log.Error("CouldnotloaddefaultpropertiesforQuartzfromQuartzassembly:{0}".FormatInvariant(ex.Message),ex);
}
}
if(props==null)
{
thrownewSchedulerConfigException(
@"Couldnotfindconfigurationsectionfromyourapplicationconfigorloaddefaultconfigurationfromassembly.
PleaseaddconfigurationtoyourapplicationconfigfiletocorrectlyinitializeQuartz.");
}
Initialize(OverrideWithSysProps(props));
}
通过上面代码分析,初始化首先会检查系统config中是否有
而jobs.xml(调度的任务和触发器plugin节点配置文件)
app.config/web.config中plugin配置
quartz.config中plugin配置指向(quartz.plugin.xml.type/quartz.plugin.xml.fileNames)
#Youcanconfigureyourschedulerineitherconfigurationsection #orinquartzpropertiesfile #Configurationsectionhasprecedence quartz.scheduler.instanceName=ServerScheduler #configurethreadpoolinfo quartz.threadPool.type=Quartz.Simpl.SimpleThreadPool,Quartz quartz.threadPool.threadCount=10 quartz.threadPool.threadPriority=Normal #--------------------------------*************plugin配置------------------------------------ #jobinitializationpluginhandlesourxmlreading,withoutitdefaultsareused quartz.plugin.xml.type=Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin,Quartz quartz.plugin.xml.fileNames=~/quartz_jobs.xml #exportthisservertoremotingcontext 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
二、基于代码的方式
这种情况直接通过代码实现的,官方DEMO很多都是如此,我们举个例子
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;usingQuartz;
usingQuartz.Impl;
usingSystem.Threading;
usingCommon.Logging;
namespaceDemo
{
classProgram
{
staticvoidMain(string[]args)
{
ILoglog=LogManager.GetLogger(typeof(Demo.HelloJob));
log.Info("-------Initializing----------------------");
//Firstwemustgetareferencetoascheduler
ISchedulerFactorysf=newStdSchedulerFactory();
ISchedulersched=sf.GetScheduler();
log.Info("-------InitializationComplete-----------");
//---------------------------------------代码添加job和trigger
//computeratimethatisonthenextroundminute
DateTimeOffsetrunTime=DateBuilder.EvenMinuteDate(DateTimeOffset.UtcNow);
log.Info("-------SchedulingJob-------------------");
//definethejobandtieittoourHelloJobclass
IJobDetailjob=JobBuilder.Create()
.WithIdentity("job1","group1")
.Build();
//Triggerthejobtorunonthenextroundminute
ITriggertrigger=TriggerBuilder.Create()
.WithIdentity("trigger1","group1")
.StartAt(runTime)
.Build();
//Tellquartztoschedulethejobusingourtrigger
sched.ScheduleJob(job,trigger);
log.Info(string.Format("{0}willrunat:{1}",job.Key,runTime.ToString("r")));
//Startupthescheduler(nothingcanactuallyrununtilthe
//schedulerhasbeenstarted)
sched.Start();
log.Info("-------StartedScheduler-----------------");
//waitlongenoughsothattheschedulerasanopportunityto
//runthejob!
log.Info("-------Waiting65seconds...-------------");
//wait65secondstoshowjobs
Thread.Sleep(TimeSpan.FromSeconds(65));
//shutdownthescheduler
log.Info("-------ShuttingDown---------------------");
sched.Shutdown(true);
log.Info("-------ShutdownComplete-----------------");
}
}
}
其实代码方式已经实现了和配置文件混搭的方式了。但是这种对方式是通过配置关联加载job与trigger配置,我们还有第三种方式,自己加载job与trigger配置文件。
三、手动加载配置文件
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingQuartz;
usingQuartz.Xml;
usingQuartz.Impl;
usingQuartz.Simpl;
usingSystem.Threading;
usingCommon.Logging;
usingSystem.IO;
namespaceDemo
{
classProgram
{
staticvoidMain(string[]args)
{
XMLSchedulingDataProcessorprocessor=newXMLSchedulingDataProcessor(newSimpleTypeLoadHelper());
ISchedulerFactorysf=newStdSchedulerFactory();
ISchedulerscheduler=sf.GetScheduler();
Streams=newStreamReader("~/quartz.xml").BaseStream;
processor.ProcessStream(s,null);
processor.ScheduleJobs(scheduler);
scheduler.Start();
scheduler.Shutdown();
}
}
}
亦或者这样
usingSystem.Text;
usingQuartz;
usingQuartz.Xml;
usingQuartz.Impl;
usingQuartz.Simpl;
usingSystem.Threading;
usingCommon.Logging;
usingSystem.IO;
namespaceDemo
{
classProgram
{
staticvoidMain(string[]args)
{
XMLSchedulingDataProcessorprocessor=newXMLSchedulingDataProcessor(newSimpleTypeLoadHelper());
ISchedulerFactorysf=newStdSchedulerFactory();
ISchedulerscheduler=sf.GetScheduler();
processor.ProcessFileAndScheduleJobs("~/quartz.xml",scheduler);
scheduler.Start();
scheduler.Shutdown();
}
}
}
目前根据源码分析大致就这几种配置方式,很灵活可以任意组合。关于quartz的使用源码很详细,并且园子量有大量的学习文章。
记住quartz的配置读取方式首先app.config/web.config---->quartz.config/Quartz.quartz.config---->quartz_jobs.xml.
通过代码方式我们可以改变quartz_jobs.xml的指向即自己新命名的xml文件
(默认的quartz_jobs.xml是在XMLSchedulingDataProcessor.QuartzXmlFileName="quartz_jobs.xml"被指定的)
方式一,通过quartz节点/quartz.config指向指定的jobs.xml。
方式二,通过XMLSchedulingDataProcessor加载指定的jobs.xml
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。