让 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。
我正在构建一个 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。