我可以让等待的 Quartz 作业按照触发顺序触发吗?

发布于 2024-09-11 07:50:46 字数 1882 浏览 6 评论 0原文

我有一个使用 Quartz Scheduler 来安排作业的应用程序。该应用程序当前运行的是 Quartz 版本 1.6.2。我的 JobStore 是 org.quartz.impl.jdbcjobstore.JobStoreTX,有一个 Oracle 数据库支持它。集群已打开,但只有一个调度程序使用数据库。我的 Quartz 线程池配置如下:

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5

我的作业长时间运行,因此当触发器触发新作业时,运行 5 个作业(我的线程池允许的最大值)是相当常见的。新触发的作业失火,我看到如下日志消息:

2011-05-20 04:09:30,097 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName1 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:08:29 05/20/2011
2011-05-20 04:09:30,120 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName1 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:09:30 05/20/2011
2011-05-20 04:09:30,125 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName2 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:08:30 05/20/2011
2011-05-20 04:09:30,138 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName2 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:09:30 05/20/2011
2011-05-20 04:11:29,998 INFO  [QuartzScheduler_scheduler-servername-111305822376676_MisfireHandler] o.q.impl.jdbcjobstore.JobStoreTX - Handling 2 trigger(s) that missed their scheduled fire-time.

一旦正在运行的作业完成,其中一个失火的作业将被拾取并正常运行。然而,Quartz 似乎随机地选取了一个失败的作业,而不考虑作业最初计划执行的顺序。理想情况下,我希望根据它们最初的火灾时间,按照它们应该运行的顺序来接它们。

一旦 Quartz ThreadPool 中的空间可用,是否可以按照触发顺序触发我的等待(失火)作业?

I have an application using the Quartz Scheduler to schedule jobs. The application is currently running Quartz version 1.6.2. My JobStore is org.quartz.impl.jdbcjobstore.JobStoreTX with an Oracle database backing it. Clustering is turned on, but there's only one scheduler using the database. My Quartz threadPool is configured as follows:

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5

My jobs are long running, so it's fairly common to have 5 jobs running (the maximum allowed by my thead pool) when triggers fire new jobs. The newly triggered jobs misfire and I see log messages like the following:

2011-05-20 04:09:30,097 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName1 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:08:29 05/20/2011
2011-05-20 04:09:30,120 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName1 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:09:30 05/20/2011
2011-05-20 04:09:30,125 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName2 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:08:30 05/20/2011
2011-05-20 04:09:30,138 INFO  [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName2 misfired job DEFAULT.DEFAULT  at:  04:09:30 05/20/2011.  Should have fired at:  04:09:30 05/20/2011
2011-05-20 04:11:29,998 INFO  [QuartzScheduler_scheduler-servername-111305822376676_MisfireHandler] o.q.impl.jdbcjobstore.JobStoreTX - Handling 2 trigger(s) that missed their scheduled fire-time.

Once a running job finishes, one of the misfired jobs will get picked up and run normally. However, Quartz seems to pick up a misfired job randomly, with no regard to the order the jobs had been originally scheduled to execute. Ideally, I'd like them to be picked up in the order they were supposed to have run, based on their original fire times.

Is it possible to make my waiting (misfired) jobs get fired in the order they were triggered once space in the Quartz ThreadPool becomes available?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

谈情不如逗狗 2024-09-18 07:50:46

当quartz 处理错过触发时间的触发器时,它将更新触发器的nextFireTime。默认情况下,如果 nextFireTime 过去超过 60 秒,则触发将被视为错过。仍然应该根据 nextFireTime 和优先级顺序选择错过的触发器,但我猜它似乎是随机的,因为某些触发器已更新,而其他触发器尚未更新。

我建议增加 org.quartz.jobStore.misfireThreshold 属性。请参阅 http://www.quartz-scheduler.org /documentation/quartz-2.x/configuration/ConfigRAMJobStore.html(尽管所有 JobStore 的属性都是相同的)。这应该会降低您的触发器被重新安排的可能性。

When quartz handles a trigger that has missed it's fire time it will update the nextFireTime of the trigger. By default a trigger will be considered missed if it's nextFireTime is over 60 seconds in the past. Missed triggers should still be selected based on nextFireTime and priority order but I'm guessing it seems random because some triggers have been updated and others haven't.

I would suggest increasing the org.quartz.jobStore.misfireThreshold property. See http://www.quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigRAMJobStore.html (although the property is identical for all JobStores). This should make it less likely for your triggers to be re-scheduled.

秋千易 2024-09-18 07:50:46

我听起来好像您遇到了失败的情况(在这种情况下,准备执行的作业多于工作线程)。设置触发器上的失火指令和/或优先级属性,以更改每个触发器在超过其触发时间后的行为方式。

此外,您可以考虑增加失火阈值,这将更改触发器在被视为失火(并将其失火指令应用于其)之前“延迟”等待线程执行的时间量。

一旦 Quartz ThreadPool 中的空间可用,是否可以按照触发顺序触发我的等待(失火)作业?

“不执行任何操作”指令将使火灾时间保持原样。

I sounds like you are running into a misfiring scenario (a scenario where there are more jobs ready to be executing than there are worker threads). Set the misfire instruction and/or priority property on the triggers to change how each behaves after it has past its fire time.

Also, you could consider increasing the misfire threshold, which would change the amount of time that a trigger can be "late" waiting for a thread to execute on before it is considered misfire (and has its misfire instruction applied to it).

Is it possible to make my waiting (misfired) jobs get fired in the order they were triggered once space in the Quartz ThreadPool becomes available?

The "do nothing" instructions will leave the fire times as-is.

離殇 2024-09-18 07:50:46

查看quartz 线程池,它使用wait()/notify()循环,这是不公平的,并且当多个线程等待时会随机选择一个新线程。

您可以使用自己的 ThreadPool 实例,这是公平的。从 SimpleThreadPool 复制代码,但用 java.util.ReentrantLock 替换 nextRunnableLock 周围的锁定,并将 true 传递给公平构造函数。在修改后的SimpleThreadPool中,使用ReentrantLock.lock()/unlock()而不是synchronized,并使用ReentrantLock.newCondition().signal()/await()而不是wait/notify,它可能会解决你的问题。

Looking at the quartz thread pool , it uses a wait()/notify() loop, which is not fair, and will randomly select a new thread when multiple threads are waiting.

You could use your own instance of ThreadPool which is fair. Copy the code from SimpleThreadPool, but replace the locking around nextRunnableLock with a java.util.ReentrantLock, passing true to the fair constructor. In your modified SimpleThreadPool, use ReentrantLock.lock()/unlock() instead of synchronized, and use ReentrantLock.newCondition().signal()/await() instead of wait/notify, and it might solve your problem.

鹊巢 2024-09-18 07:50:46

如果是 CronTrigger,方法 updateAfterMisfire() 可能会在 new Date() 情况下重新安排任务 MISFIRE_INSTRUCTION_FIRE_ONCE_NOW代码>政策。

如果多个任务失败,其中几个任务可能会同时(同一毫秒)重新安排,因为计算机运行速度很快。

因此,如果没有定义优先级,调度程序将根据键或全名选择第一个下一个任务,所有任务都具有相同的 NextFireTime

例如,updateAfterMisfire() 方法应该使用 Thread.sleep(25) 将任务重新安排到唯一的日期

In case of a CronTrigger, the method updateAfterMisfire() may re-schedule the task at new Date() case MISFIRE_INSTRUCTION_FIRE_ONCE_NOW policy.

If several task are misfired, several of them may be rescheduled at the same time (same millisecond), because computer runs fast.

As a consequence, and if no priority defined, the scheduler will pick-up the first next task, all with same NextFireTime, according to key or full name.

updateAfterMisfire() method should have re-schedule the task to a unique date using a Thread.sleep(25), as an example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文