让 Quartz.net 忽略失火

Getting Quartz.net to ignore misfires

我正在构建一个 windows 服务,该服务正在执行一项计划任务,该任务使用 Quartz.net [定期(每分钟一次)处理命令队列(来自遗留系统)

如果任务花费的时间超过 1 分钟,这很不寻常但在某些情况下是可能的,我希望它简单地忽略它错过触发的触发器。

但是我似乎无法做到这一点。它进行处理,然后快速连续触发它错过的所有触发器。据我了解,您可以为失火设置一个阈值,但我似乎无法使它正常工作。

我在作业上使用 [DisallowConcurrentExecution()] 以确保在任何时候只有一个作业实例是 运行。

下面是几个片段。首先传递一些配置信息 - 这是你设置失火阈值的方式吗?

    NameValueCollection config = new NameValueCollection();
    config.Add("quartz.jobStore.misfireThreshold", "600000");

    schedFact = new StdSchedulerFactory(config);

使用我认为正确的 Ignore misfires 设置构建触发器:

    var trigger = TriggerBuilder.Create()
                    .WithIdentity("trigger1", "group1")
                    .StartNow()
                    .WithSimpleSchedule(   x => x.WithMisfireHandlingInstructionIgnoreMisfires()
                    .WithIntervalInSeconds(60)
                    .RepeatForever())
                    .Build();

非常感谢您的想法。

工作代码: 在这一点上只是玩弄粗略的想法所以只是 运行 在控制台应用程序中并随机延迟作业以便它在为此设置为 10 秒的间隔内拍摄。在延迟几次后,所有备份的失火都会快速连续地发生。

[DisallowConcurrentExecution()]
public class SomeJob : IJob
{
    public SomeJob() { }
    public void Execute(IJobExecutionContext context)
    {
        Random rnd = new Random(DateTime.UtcNow.Second);
        int delay = rnd.Next(2);
        Console.WriteLine("Executing Job with delay of "+ delay + "  at " + DateTime.UtcNow.ToString());

        if (delay == 1)
        {
            System.Threading.Thread.Sleep(1000 * 25); // sleep for 25 seconds
        }
    }
}





Example console output:
Executing Job with delay of 1  at 21/05/2015 21:27:17
Executing Job with delay of 1  at 21/05/2015 21:27:42
Executing Job with delay of 0  at 21/05/2015 21:28:07 <-- stacked misfires
Executing Job with delay of 0  at 21/05/2015 21:28:07 <--
Executing Job with delay of 0  at 21/05/2015 21:28:07 <--
Executing Job with delay of 0  at 21/05/2015 21:28:07 <--
Executing Job with delay of 0  at 21/05/2015 21:28:16
Executing Job with delay of 0  at 21/05/2015 21:28:26
Executing Job with delay of 1  at 21/05/2015 21:28:36
Executing Job with delay of 0  at 21/05/2015 21:29:01
Executing Job with delay of 0  at 21/05/2015 21:29:01
Executing Job with delay of 1  at 21/05/2015 21:29:06

WithMisfireHandlingInstructionIgnoreMisfires() 是您想要的错误方法,这并不意味着作业不会触发失火,这意味着它将尽快触发所有错过的触发器,然后返回到普通时间表。这就是您看到的情况。

你需要的是WithMisfireHandlingInstructionNextWithRemainingCount()。这将向调度程序发出信号以忽略失火并等待下一个预定时间。 Misfiring strategies 可能有点令人困惑,为了简洁的解释看 here(它是针对 java 调度程序的,但没关系)。

即使采用正确的策略,您也需要了解失火阈值的工作原理 - 如果您弄错了,失火的触发器可能仍会启动。

来自文档:“失火是触发器必须错过其下一次点火时间的时间跨度,以便将其视为“失火”并因此失火已应用指令”。

您已将该值设置为 600000 毫秒(此值适用于所有触发器,不幸的是每个触发器没有阈值)- 仅当您的触发器触发时才会应用 misfire 策​​略 600000 毫秒 它应该被解雇的时间之后。您可以根据您的要求降低或增加它。

有关失火阈值的更多信息,请阅读 here