zoukankan      html  css  js  c++  java
  • 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

    这2个是对触发器和job本身的行为监听器,这样更好方便跟踪Job的状态及运行情况。  

    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; } }
        }

    主函数添加:

               //添加监听器到指定的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位表达式,最后一位非必选。

    表达式从左到右,依此是秒、分、时、月第几天、月、周几、年。下面表格是要遵守的规范:

    字段名允许的值允许的特殊字符
    Seconds 0-59 , - * /
    Minutes 0-59 , - * /
    Hours 0-23 , - * /
    Day of month 1-31 , - * ? / L W
    Month 1-12 or JAN-DEC , - * /
    Day of week 1-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触发。

    Quartz.Net线程池

    线程池数量设置:

    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,如果有上百个JOB,可在服务器承受范围内适量增加线程数量。     

    总结

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

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

    quartz中监听器还有SchedulerListener,使用方法基本一样。 

    本文基于自用经验和官方文档代码来写的,部分是直接翻译的。 

    Quartz.Net官方教程http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/index.html

  • 相关阅读:
    flask_第一个程序
    Web框架_MVC vs MVT
    python_使用qrcode生成二维码
    HDU 4641
    SPOJ NSUBSTR
    SPOJ LCS2 多个串的最长公共子串
    SPOJ LCS 后缀自动机找最大公共子串
    POJ 1509 循环同构的最小表示法
    HDU 4821 字符串hash
    SPOJ GSS1 静态区间求解最大子段和
  • 原文地址:https://www.cnblogs.com/mushroom/p/4104484.html
Copyright © 2011-2022 走看看