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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。