分布式作业调度系统-Quartz组件

Quartz.NET是一个功能齐全的开源作业调度系统,(Quartz读音:[kwɔːts],发音类似中文“扩儿词”),从最小的应用程序到大型企业系统都可以使用。Quartz.NET是一个用C#编写的纯.NET库,是非常流行的开源Java作业调度框架Quartz的一个对等功能的实现。其简单的使用方式这里做一下介绍。网上比比皆是,依旧自己在纪录一遍的意义在于:加深记忆和理解,方便重用和查找。

 

基本结构

首先咱们先看一下quartz的整体结构,如图:

每一个作业(任务/工作)都有一个作业调度器进行管理,作业调度器的启动需要三个条件:1基础信息(数据信息,执行程序),2、触发条件。

 

入门使用

1、咱们在使用的时候,首先需要创建一个作业调度池:

ISchedulerFactory schedf = new StdSchedulerFactory();//工厂
IScheduler sched =await schedf.GetScheduler();//作业调度器
sched.Start();//启动,开始调度

2、为了方便后面的代码,咱们先创建一个执行程序:

    [DisallowConcurrentExecutionAttribute]
    public class HelloJob : IJob
    {
        public Task Execute(IJobExecutionContext context)
        {
            //读取传递的数据
            context.JobDetail.JobDataMap.GetString("这是ke");
            Console.WriteLine(context.RefireCount);
            Console.WriteLine("Info From HelloJob:" + DateTime.Now.ToString());
            return Task.FromResult(0);
        }
    }

3、创建基础数据,指定执行的代码和传递的数据

IJobDetail job = JobBuilder.Create<HelloJob>().UsingJobData("这是key","value").Build();

4、触发器(就是执行策略)有4类,下面通过创建一个简单的触发器,来分别说一下这几类触发器:

      a、一般简单的触发策略可以如下写:

ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(3).WithRepeatCount(9)).Build();

含义是:三秒执行一次,一直到执行次数计数器值为9,当第一次执行,执行的计数器等于0),总共执行10次。

      b、简单的触发策略如果不设置job启动时间点,默认都是按照程序启动时间开始计算的,下面创建一个在10秒后才开始的触发策略:

 ISimpleTrigger trigger = (ISimpleTrigger)((TriggerBuilder.Create().StartAt(DateTimeOffset.Now.AddSeconds(10))).WithSimpleSchedule(x =>x.WithIntervalInSeconds(1).WithRepeatCount(2)).Build());

含义是:从当前时间算起,10秒后启动,一秒一次,执行三次(执行的计数器数=2),当然也可以使用EndAt()设置结束时间

注:其实这种一直“.”的写法,我不喜欢,可读性太差了。

      c、使用自定义表达式定义执行策略,网上有表达式生成工具:http://cron.qqe2.com/

            //定义执行策略
            var _mySchedule = CronScheduleBuilder.CronSchedule("0/5 0 14,18 * * ? *");
            //构建触发器
            ICronTrigger _myTrigger = (ICronTrigger)(TriggerBuilder.Create().WithIdentity("名字", "组名").WithSchedule(_mySchedule).Build());

      d、其他的触发器策略类型:CalendarIntervalTriggerImpl和DailyTimeIntervalTriggerImpl,具体如何使用建议查看文档。

5、加入到作业调度器中,此时因为作业调度已经启动,所以,任务就已经被安排下去了。就是待执行的了,咱们就不用管了,由作业调度器进行安排什么时候执行如何执行等等

            sched.ScheduleJob(job, trigger);

 

Misfire策略

 misfire,[ˌmɪsˈfaɪə(r)],不奏效,不起火。在作业调度中的作用就是,如果作业线程“不奏效”,咱们可以使用对应办法就行处理。

1、先说CronTrigger的

withMisfireHandlingInstructionFireAndProceed(默认)

以当前时间为触发频率立刻触发一次执行,然后按照Cron频率依次执行

withMisfireHandlingInstructionIgnoreMisfires

a、以错过的第一个频率时间立刻开始执行
b、重做错过的所有频率周期后
c、当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行

withMisfireHandlingInstructionDoNothing

a、不触发立即执行
b、等待下次Cron触发频率到达时刻开始按照Cron频率依次执行

2、SimpleTrigger的

withMisfireHandlingInstructionFireNow

a、以当前时间为触发频率立即触发执行
b、执行至FinalTIme的剩余周期次数
c、以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
d、调整后的FinalTime会略大于根据starttime计算的到的FinalTime值

withMisfireHandlingInstructionIgnoreMisfires

a、以错过的第一个频率时间立刻开始执行
b、重做错过的所有频率周期
c、当下一次触发频率发生时间大于当前时间以后,按照Interval的依次执行剩下的频率
d、共执行RepeatCount+1次

withMisfireHandlingInstructionNextWithExistingCount

a、不触发立即执行
b、等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
c、以startTime为基准计算周期频率,并得到FinalTime
d、即使中间出现pause,resume以后保持FinalTime时间不变

withMisfireHandlingInstructionNextWithRemainingCount

a、不触发立即执行
b、等待下次触发频率周期时刻,执行至FinalTime的剩余周期次数
c、以startTime为基准计算周期频率,并得到FinalTime
d、即使中间出现pause,resume以后保持FinalTime时间不变

withMisfireHandlingInstructionNowWithExistingCount(默认)

a、以当前时间为触发频率立即触发执行
b、执行至FinalTIme的剩余周期次数
c、以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
d、调整后的FinalTime会略大于根据starttime计算的到的FinalTime值

withMisfireHandlingInstructionNowWithRemainingCount

a、以当前时间为触发频率立即触发执行
b、执行至FinalTIme的剩余周期次数
c、以调度或恢复调度的时刻为基准的周期频率,FinalTime根据剩余次数和当前时间计算得到
d、调整后的FinalTime会略大于根据starttime计算的到的FinalTime值

MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT

a、此指令导致trigger忘记原始设置的starttime和repeat-count
b、触发器的repeat-count将被设置为剩余的次数
c、这样会导致后面无法获得原始设定的starttime和repeat-count值

 

评论 (2) -

  • 调度系统器如何和宿主系统通信啊?文章内你好像没有提起。
    • 没明白你的意思,这个本身就是宿主程序的一部分,就是一个类库,直接调用/访问想操作的内容就可以了。

添加评论

Loading