0

问候,您友好的社区 Quartz.NET n00b 回来了!

我有一个 Windows 服务在基于 Quartz.NET CronTrigger 的调度方案上运行 iStatefulJob 实例...用于调度作业的 CRON 字符串:“0 0/1 * * * ? *”

一切都很好。但是,如果我有一个作业设置为在每分钟的 X:00 标记处运行,并且该作业恰好运行超过一分钟,我注意到后续作业在作业完成后立即运行执行,而不是等到下一次计划运行,有效地“排队”而不是仅仅跳过作业直到下一次计划运行。

我在触发器中放入了一个 CronTrigger MisfireInstruction 的 DONOTHING 指令,但是当作业超出其下一个预定的执行计划时,也会发生完全相同的事情。

如何让 iStatefulJob 实例仅在它当前正在运行时跳过计划的执行触发器,而不是让它延迟到第一次执行完成?

我明确设置了 trigger.MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;

...但是,对于计划每分钟运行一次需要 90 秒才能完成的作业,我没有“什么都不做”,而是遇到以下执行日志:

  • 作业在上午 9:00:00 运行,在上午 9:01:30 结束 <- 作业运行时间为 1:30
  • 作业在上午 9:01:30 运行,在上午 9:03:00 完成 <- 应该在 9:01:00 运行的后续作业
  • 作业在上午 9:04:00 运行,在上午 9:05:30 完成 <- 这不应该在 9:03:00 运行吗?
  • 作业在上午 9:05:30 运行,在上午 9:07:00 完成 <- 应该在 9:05:00 运行的后续作业
  • 作业在上午 9:08:00 运行,在上午 9:09:30 完成 <- 这不应该在 9:07:00 运行吗?

...似乎它第一次正确运行,在一分钟...随着 90 秒的作业执行时间到期,延迟 30 秒,然后,而不是等到下一个完整的分钟,而是在 30 秒立即执行标记...奇怪的是,它然后在分钟标记上完成了第二个作业,但是等到下一个分钟标记执行而不是向后运行它 2-back...

当它没有在 :30 标记上运行时,它似乎在每次运行时都能正常工作......

获得一份工作的最佳方法不是延迟/排队,而是跳过直到它空闲并且下一个时间表成熟?

编辑:我尝试使用相同的 DONOTHING 触发失火指令返回 iJobs 而不是 iStatefulJobs,但是尽管先前的执行仍然处于活动状态,但该作业每分钟执行一次。如果它当前正在使用 iJob 或 iStatefulJob 运行,我似乎无法让它跳过预定的运行......

编辑#2:我认为我的触发器永远不会失火,这就是为什么 DoNothing 作为失火指令是无用的......鉴于这种情况,我想我需要另一种机制来检测调度的作业实例是否正在运行以确保该作业跳过其下一次执行,直到其下一个预定时间,而不是将其延迟到第一个实例完成......

EDIT3:我尝试向 iStatefulJob jobdatamap 添加一个名为“IsRunning”的元素......我在执行序列开始时将其设置为 TRUE,然后在作业完成后将其返回为 false。在执行之前,它会检查显然在作业之间持久存在的元素,如果它检测到它是真的,则过早地退出执行(记录“JOB SKIPPED!”)......不幸的是,这不起作用,原因可能很明显:如果作业按照上面列出的时间表运行,那么作业永远不会同时运行,因为它会延迟运行直到作业结束,所以这个检查是没有用的。根据文档,从 iStatefulJob 返回到 iJob 在这里无济于事,因为 jobdatamap 仅在 Stateful 作业类型的作业之间持续存在......

我还没有解决如何跳过计划的工作而不是将其延迟到当前迭代完成......如果有人有想法,你就是救星!:)

4

1 回答 1

2

它应该是由 RAMJobStore ( http://quartznet.sourceforge.net/apidoc/topic2722.html ) 的 misfireThreshold 引起的。

触发器必须错过其下一次触发时间的时间跨度,以便将其视为“未触发”并因此应用其未触发指令。

默认为 60 秒。因此,工作直到超过 misfiredThreshold 值才被视为“失败”。

要解决此问题,只需降低此阈值(以下代码设置为 1 毫秒):

...   
properties["quartz.jobStore.misfireThreshold"] = "1";
...
schedulerFactory = new StdSchedulerFactory(properties);

它应该可以解决问题。

于 2011-06-16T22:35:53.457 回答