首页 > 代码库 > Net作业调度(二) - Quartz.Net进阶

Net作业调度(二) - Quartz.Net进阶

介绍

前面我们介绍Quartz.Net的基本用法,但在实际应用中,往往有更多的特性需求。   比如记录job执行的执行历史,发邮件等。

 

目录

1:Quartz.Net插件

2:TriggerListener,JobListener

3:Cron表达式

4:Quartz.Net 线程池

5:总结

 

Quartz.Net插件

     Quartz.net 自身提供了一个插件接口(ISchedulerPlugin)用来增加附加功能。 我们来看下官方定义:

  public interface ISchedulerPlugin    {        void Initialize(string pluginName, IScheduler sched);       //关闭调度器        void Shutdown();        //插件启动        void Start();    }

 继承接口,实现自己的插件。

 public class MyPlugin : ISchedulerPlugin    {        public void  Initialize(string pluginName, IScheduler sched)        {            Console.WriteLine("实例化");        }        public  void Start()        {             Console.WriteLine("启动");        }        public  void Shutdown()        {            Console.WriteLine("关闭");        }    }

  主函数里面配置我们实现的插件,注释部分,一句话搞定。

static void Main(string[] args)        {            var properties = new NameValueCollection();           //MyPlugin 自定义名称。    "命名空间.类名,程序名称"            properties["quartz.plugin.MyPlugin.type"] = "QuartzDemo3.MyPlugin,QuartzDemo3";             var schedulerFactory = new StdSchedulerFactory(properties);            var scheduler = schedulerFactory.GetScheduler();            var job = JobBuilder.Create<HelloJob>()                .WithIdentity("myJob", "group1")                .Build();            var trigger = TriggerBuilder.Create()                                .WithIdentity("mytrigger", "group1")                                .WithCronSchedule("/2 * * ? * *")                                .Build();            scheduler.ScheduleJob(job, trigger);            scheduler.Start();            Thread.Sleep(6000);            scheduler.Shutdown(true);            Console.ReadLine();        }

  运行结果如下:

 

 

 

TriggerListener,JobListener

ITriggerListener官方定义的接口,这里我们直接继承实现。

 

public class MyTriggerListener : ITriggerListener    {        private string name;        public void TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode)        {            Console.WriteLine("job完成时调用");        }        public void TriggerFired(ITrigger trigger, IJobExecutionContext context)        {            Console.WriteLine("job执行时调用");        }        public void TriggerMisfired(ITrigger trigger)        {            Console.WriteLine("错过触发时调用(例:线程不够用的情况下)");        }        public bool VetoJobExecution(ITrigger trigger, IJobExecutionContext context)        {            //Trigger触发后,job执行时调用本方法。true即否决,job后面不执行。            return false;        }        public string Name { get { return name; } set { name = value; } }    }

main函数添加:

           //添加监听器到指定的trigger            scheduler.ListenerManager.AddTriggerListener(myJobListener, KeyMatcher<TriggerKey>.KeyEquals(new TriggerKey("mytrigger", "group1")));            ////添加监听器到指定分类的所有监听器。            //scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.GroupEquals("myJobGroup"));            ////添加监听器到指定分类的所有监听器。            //scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.GroupEquals("myJobGroup"));           ////添加监听器到指定的2个分组。            //scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.GroupEquals("myJobGroup"), GroupMatcher<TriggerKey>.GroupEquals("myJobGroup2"));            ////添加监听器到所有的触发器上。            //scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.AnyGroup());            scheduler.Start();

  

JobListener同理,这里不多做描述。

 

Cron表达式

quartz中的cron表达式和Linux下的很像。 像  "/5 * * ? * * *"  这样的7位表达式,最后一位非必选。 从左到右,下面是属性。

字段名允许的值特殊字符
Seconds0-59, - * /
Minutes0-59, - * /
Hours0-23, - * /
Day of month1-31, - * ? / L W
Month1-12 or JAN-DEC, - * /
Day of week1-7 or SUN-SAT, - * ? / L #
Year空, 1970-2099, - * /

     

特殊字符解释
,或的意思。例:分钟位 5,10  即第5分钟或10分都触发。 
/a/b。     a:代表起始时间,b频率时间。 例; 分钟位  3/5,  从第三分钟开始,每5分钟执行一次。
*频率。    即每一次波动。    例;分钟位 *  即表示每分钟 
-区间。    例: 分钟位   5-10 即5到10分期间。 
?任意值 。     即每一次波动。只能用在DayofMonth和DayofWeek,二者冲突。指定一个另一个一个要用?
L表示最后。 只能用在DayofMonth和DayofWeek,4L即最后一个星期三
W工作日。  表示最后。 只能用在DayofWeek
#4#2。 只能用DayofMonth。 某月的第二个星期三  

 

实例介绍

”0 0 10,14,16 * * ?"    每天10点,14点,16点 触发。

"0 0/5 14,18 * * ?"    每天14点或18点中,每5分钟触发 。

"0 4/15 14-18 * * ?"       每天14点到18点期间,  从第四分钟触发,每15分钟一次。

"0 15 10 ? * 6L"        每月的最后一个星期五上午10:15触发。

 

 

ThreadPool

properties["quartz.threadPool.threadCount"] = "5";  //线程池设置

这个线程池的设置,是指同时间。调度器能执行Job的最大数量。

quartz是用每个线程跑一个job。 上面的设置,可以解释是job并发时能执行5个job。剩下的job如果触发时间恰好到了,当前job会暂停状态,直到有可用的线程。

如果在指定的时间还没可用线程,会触发misfired。

 

quartz 给我提供了IThreadPool接口,我们也可以用其他的线程实现。下面是配置项。

properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"; 

 

一般来说我们的作业调度很少并发触发大量job。当然如果你有上百个,那就根据实际需要评估,增加线程数量吧。     

 

 

总结

官方有LoggingTriggerHistoryPlugin,LoggingJobHistoryPlugin  已实现的,触发器和job历史记录的插件。

Quartz.Plugin 命名空间下有官方实现的一些插件,也可以自己增加扩展。

 

quartz中监听器还有SchedulerListener,使用方法基本一样。 另外监听器都是操作的。

 

本文基于自用经验,和官方文档代码来写的,有些是直接翻译的。 如果错误之处,希望请指出。

 

 

Net作业调度(二) - Quartz.Net进阶