这里有3个原因:
1.所有的woker thread(工作线程; 辅助线程)都在运行其他的job
2.scheduler(调度器)down了(关于这个down。我不太明确是shutdown了。。还是挂掉了。因此下文依旧用down。)
3.任务被安排在过去的某一时刻启动(此可能为代码错误)

我的

我的解决方法:修改quartz.properties文件中的org.quartz.threadPool.threadCount的值增大。(从原来的10增大到20),

      最近公司加了好多定时任务,导致线程不够用,至此quartz挂掉。

以下来源于网上:

可以简单地通过配置quartz.properties文件中的org.quartz.threadPool.threadCount,来增加worker thread的数量(默认为10)。但是当整个 application/server/scheduler (调度器)挂掉的时候,这方法仍然是无效的。这种Quartz无法启动指定触发器情况,叫做 misfire(http://fanyi.baidu.com/#en/zh/misfire 以下统一用misfire,汉语无法贴切表达)。
你知道当这种情况发生的时候,Quartz能做些什么吗? 其实,Quartz有许多的策略(叫misfire instructions,失火指示)可以处理问题,并且当你没有去想这方面问题的时候,它也有许多默认策略。但是为了使你的应用更加稳定和可预测(尤其是在高负载和可维护性上),你应该有意识的去确保triggers 和 jobs工作正常。

基于你用的trigger,会有不同的配置选项(对misfire instructions有效)。当然,不同的trigger也会使Quartz有不同的行为(叫做smart policy,明智的决策)。尽管文档中有misfire instructions的描述,但是我发现都很难理解它所想表达的意思,因此,我写下这篇简短的总结。

在我深入细节之前,还有一个配置需要说明下:org.quartz.jobStore.misfireThreshold(毫秒级),默认是60000(一分钟)。它定义了trigger被认为是misfired了的时限。

基于默认配置,如果trigger应该在30秒以前被触发,那么很愉快地,Quartz就把它搞定了。这种延迟(delay)不能叫失火。

然而当trigger被发现,延迟了61秒时,那么专门的“失火处理者(misfire handler thread)”就会按照misfire instructions去处理它了。

为了测试效果,我们将这个时间设置为1000(即1秒),这样就能很快的测试“失火”了。

第一个例子,是一个不需要重复触发的普通trigger,我们来看看普通trigger调度器是怎么处理“失火”,并让它运行一次的:

【原文:Simple trigger without repeating In our first example we will see how misfiring is handled by simple triggers scheduled to run only once:】

view source print?
1.val trigger = newTrigger().
2.startAt(DateUtils.addSeconds(new Date(), -10)).
3.build()

同样的trigger,但是明确设置了misfire instruction handler(失火处理者):

view source print?
1.val trigger = newTrigger().
2.startAt(DateUtils.addSeconds(new Date(), -10)).
3.withSchedule(
4.simpleSchedule().
5.withMisfireHandlingInstructionFireNow() //MISFIRE_INSTRUCTION_FIRE_NOW
6.).
7.build()

为了测试,我将trigger设置为10秒前被调度(即当创建后,就已经晚于启动时间10秒)。在实际使用时,我们基本上永远不会这么设置。

换句话说,如果我们正确的设置了trigger,但是当需要被调度的时候,调度器down了或者没有空闲的worker thread了。那么,Quartz怎么处理这种extraordinary(罕见,古怪)的情况呢?

在第一段代码中,没有设置misfire instruction(so called smart policy is used in that case 这句不太会翻译。。。。)。

第二段代码中,明确指定了当misfire发生时,我们希望采取的行为。

来看下表:

指令 Instruction 意义 Meaning
smart policy - default See: withMisfireHandlingInstructionFireNow
withMisfireHandlingInstructionFireNow
MISFIRE_INSTRUCTION_FIRE_NOW
调度器发现misfire情况后,立即执行job。
这是smart policy。
例如:
你让一些系统清理功能在2点执行。但是很不幸,应用在那段时间由于维护,关闭了,直到3点才恢复。这样trigger就misfire了,然后调度器会尝试修复这种情况,在3点启动后,尽快执行。
withMisfireHandlingInstructionIgnoreMisfires
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
See: withMisfireHandlingInstructionFireNow
withMisfireHandlingInstructionNextWithExistingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
See: withMisfireHandlingInstructionNextWithRemainingCount
withMisfireHandlingInstructionNextWithRemainingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
什么都不做。misfire被忽略了,并且没有后续的执行。当你想要彻底放弃被misfire的执行时,可以使用这个指令。
例如:
trigger是要启动录制一个电视节目。但是被misfire了,2个小时候,才发现。  
【PS: 这个不是太理解,只是按照原文翻译过来,如果要用,请自行测试。。。】
withMisfireHandlingInstructionNowWithExistingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
See: withMisfireHandlingInstructionFireNow
withMisfireHandlingInstructionNowWithRemainingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
See: withMisfireHandlingInstructionFireNow

普通trigger重复执行指定次数。这种情形更加复杂。想象一下,我们有一些需要重复执行指定次数的job:

view source print?
01.val trigger = newTrigger().
02.startAt(dateOf(900)).
03.withSchedule(
04.simpleSchedule().
05.withRepeatCount(7).
06.withIntervalInHours(1).
07.WithMisfireHandlingInstructionFireNow()  //or other
08.).
09.build()

在这个例子中,trigger从今天9点开始(startAt(dateOf(9, 0, 0)),共触发8次(第一次执行,和7次重复)。

按理,最后一次执行应该在下午4点被触发。假设由于某些原因,在9点和10点调度器没有执行job,并且直到10:15才被系统发现misfire,也就是misfire了2次。这种情况下,调度器会怎么样呢?

指令 Instruction 意义 Meaning
smart policy - default See:withMisfireHandlingInstructionNowWithExistingCount
withMisfireHandlingInstructionFireNow
MISFIRE_INSTRUCTION_FIRE_NOW
See:withMisfireHandlingInstructionNowWithRemainingCount
withMisfireHandlingInstructionIgnoreMisfires
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
尽快启动所有被启动的trigger,并将调度置为正常。
例如:
在我们上面的例子中,调度器会立即执行9点和10点的任务,并等待11点时,继续按正常的调度执行。
备注:当处理misfire时,我们同样要注意到,实际job执行的时间,已经滞后于应该执行的时间。这意味着,你不能简单地的依赖当前系统时间,而是应该使用 JobExecutionContext .getScheduledFireTime()去获取。

view source print?
1.def execute(context: JobExecutionContext) {
2.val date = context.getScheduledFireTime
3.//...
4.}

withMisfireHandlingInstructionNextWithExistingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
调度器不会马上有反应。它会等待下一次执行,然后根据应该调度次数去运行trigger。
See also: withMisfireHandlingInstructionNextWithRemainingCount
例如:
在10点15发现2次misfire。调度器会等到11点,继续执行,并会每小时执行1次,共执行8次调度操作,直到下午6点停止(本该4点停止的。)
withMisfireHandlingInstructionNextWithRemainingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
调度器会抛弃被misfire的操作,然后等待下次执行。这样,执行的总次数,就会小于配置的次数。
例如:在10点15,2次misfire的执行都被丢弃了。调度器会等到下个执行时间-11点,然后继续触发其余的trigger,直到4点。事实上,这种情况就像misfire从未发生过一样。
withMisfireHandlingInstructionNowWithExistingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
第一次misfire的trigger会立即执行,而后会按设置的间隔,依次执行剩余的trigger。实际上,就像misfire的trigger的第一次触发时间,被平移到了当前时间。
例如:
调度器会在10点15第一次运行misfire的trigger,然后隔1个小时,在11点15执行第二次。共执行8次,最后一次,在下午5点15。

withMisfireHandlingInstructionNowWithRemainingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT

第一次misfire的操作,被立即执行。其余被misfire的操作,会被抛弃。
剩余没有被misfire的trigger,会按固定间隔被触发。
例如:
调度器会在10点15运行第一次被misfire的操作(9点的。)。然后,它抛弃其余被misfire的(10点那一次)。最后,它会等1小时继续触发6个trigger:
11:15,12:15.... 4:15 PM。

这是一个基于指定间隔、并重复无数次的trigger:

view source print?
01.val trigger = newTrigger().
02.startAt(dateOf(900)).
03.withSchedule(
04.simpleSchedule().
05.withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY).
06.withIntervalInHours(1).
07.WithMisfireHandlingInstructionFireNow()  //or other
08.).
09.build()

trigger应该从今天9点开始(startAt(dateOf(9, 0, 0)),每隔小时触发一次。然而调度器在9点到10点都没有执行job(比如关闭了系统、线程不够等等。。前面有介绍),并且在10点15时才被发现,misfire了2次。这种情况比那种执行执行次数的trigger更加普遍。

指令 Instruction 意义 Meaning
smart policy - default See:withMisfireHandlingInstructionNowWithExistingCount
withMisfireHandlingInstructionFireNow
MISFIRE_INSTRUCTION_FIRE_NOW
See: withMisfireHandlingInstructionNowWithRemainingCount
withMisfireHandlingInstructionIgnoreMisfires
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
https://jira.terracotta.org/jira/browse/QTZ-283
调度器会立即执行所有misfire的trigger,然后继续正常调度。
例如:
9点和10点的trigger会立即执行,下次执行将按计划执行(下一次是11点执行)。

withMisfireHandlingInstructionNextWithExistingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
See:withMisfireHandlingInstructionNextWithRemainingCount
withMisfireHandlingInstructionNextWithRemainingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
不做任何事情,misfire的情况被忽略掉。然后,调度器按设置的间隔等待下次执行。
例如:
9点和10点misfire的执行被忽略掉。第一次执行会在11点会开始。
Example scenario: Misfired execution at 9 and 10 AM are discarded. The first execution occurs at 11 AM.

withMisfireHandlingInstructionNowWithExistingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
See:withMisfireHandlingInstructionNowWithRemainingCount
withMisfireHandlingInstructionNowWithRemainingCount
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT

第一次misfire的执行会被立即运行,其余的被忽略。下次执行会在设置的间隔时间后被触发。实际上,就是第一次执行被推迟到了当前时间。
例如:
调度器在10点15立即执行misfire的trigger,然后等待一个小时后,在11点15时,执行第二次。以后会每隔一小时。

定时触发    CRON trigger

定时触发是Quartz中最常见的。它有另外两个有效的trigger:DailyTimeIntervalTrigger(比如每25分钟一次)和CalendarIntervalTrigger(比如5个月执行一次)。They support triggering policies not possible in both CRON and simple triggers.(不会译- -!),但是他们和CRON trigger一样,支持同样的misfire handling instructions(失火处理指令)。

view source print?
1.val trigger = newTrigger().
2.withSchedule(
3.cronSchedule("0 0 9-17 ? * MON-FRI").
4.withMisfireHandlingInstructionFireAndProceed()  //or other
5.).
6.build()

这个例子是,trigger在每周一到周五的早上9点到下午5点间,每小时被触发一次。但是两次触发被misfire了,并且在10点15时,才发现这个情况。请注意,他们的失火指令效果与普通trigger是不同的:

指令 Instruction 意义 Meaning
smart policy - default See: withMisfireHandlingInstructionFireAndProceed
withMisfireHandlingInstructionIgnoreMisfires
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
https://jira.terracotta.org/jira/browse/QTZ-283
所有被misfire的执行会被立即执行,然后按照正常调度继续执行trigger。
例如:
9点和10点的执行(misfire的2个)被立即执行,下次执行将在11点被准时执行。
withMisfireHandlingInstructionFireAndProceed
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
立即执行第一次misfire的操作,并且放弃其他misfire的(类似所有misfire的操作被合并执行了)。然后继续按调度执行。无论misfire多少次trigger的执行,都只会立刻执行1次。
例如:
9点和10点的被合并执行一次(换句话说,10点需要执行的那次,被pass了)。下次执行将在11点被准时执行。
withMisfireHandlingInstructionDoNothing
MISFIRE_INSTRUCTION_DO_NOTHING
所有被misfire的执行都被忽略掉,调度器会像平时一样等待下次调度。
例如:
9点和10点的被忽略掉,好像什么都没发生一样。下次执行将在11点被执行。
   

QTZ-283Note: QTZ-283: MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY not working with JDBCJobStore - apparently there is a bug when JDBCJobStore is used, keep an eye on that issue. (在用JDBCJobStore 时,MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 没有生效。显然,这是在使用JDBCJobStore时的一个bug,关注下。)

如你所有,根据实际的设定,不同的trigger会有不同的行为。此外,虽然它提供了smart policy(明智的决策),但是真正使用时,还是要取决于业务需求。

从本质上看,主要有三种策略:忽略,立即运行然后继续正常执行,忽略misfire的并等待下次执行。( 原文: ignore, run immediately and continue and discard and wait for next. )

它们有不同的应用场景:

当你需要确保每次调度任务都要被执行的时候,即时它意味着多个misfire的trigger会被触发,那么用ignore policies。试想一下,有一个任务,需要每小时,都根据上一小时的订单去生成报表。如果服务被关闭了8个小时,那你可能仍然是尽快得到那些报表的。这种情况下,配置ignore policies,调度器会尽快将那8小时的调度任务运行一遍的。尽管晚了几个小时,但是仍然是被执行了(最终报告到手了。^_^)。

当你需要任务被定期执行,并且当出现misfire的情况后立即运行一次的时候,那么使用now* policies。试想一下,一个任务是每分钟清空文件夹 /tmp。如果调度器在20分钟内繁忙,最后终于可以执行这个任务了,那么你肯定不会希望它执行20次的!一次就足够了,但是要尽快执行。而后,再回到正常的执行间隔--1分钟。

当你希望任务能在特定时间点运行的时候,使用next* policies不错。比如你需要在每个整点后15分钟抓取股票的价格。它们的变化非常快,然后现在已经整点后20分了,那么不必烦恼。你刚好错过了5分钟,但是现在你已经不在乎(那时候的价格)了。这时,一个时间间隙总好过一个不准确的值。这种情况Quartz只要跳过misfire的操作,等待下次执行就好了。

转载于:https://www.cnblogs.com/baixiuhua/p/8566919.html

quartz问题记录-missed their scheduled fire-time相关推荐

  1. Handling 2 trigger(s) that missed their scheduled fire-time,JobPersistenceException: Couldn't store

    测试服应用 启动, quartz模块 报错 Handling 2 trigger(s) that missed their scheduled fire-time MisfireHandler: Er ...

  2. Quartz学习记录

    1.1 什么时候需要任务调度? 1.1.1 任务调度的背景 在业务系统中有很多这样的场景: 1.账单日或者还款日上午 10 点,给每个信用卡客户发送账单通知,还款通知.如 何判断客户的账单日.还款日, ...

  3. Abp集成Quartz.net记录

    编写了一个任务分配系统,基本流程是任务发起者发起一个周期任务,指定好周期,接收人定期收到任务.刚开始使用的是Hangfire,很容易跑起来,还自带一个管理控制台.跑起来后发现Hangfire有一些不足 ...

  4. Spring框架中的Quartz定时任务使用笔记(通过@Scheduled注解的方式实现)

    1.修改spring的xml配置信息 applicationContext.xml 三个部分内容 1.xmlns添加:xmlns:task="http://www.springframewo ...

  5. quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析 引言 quartz集群架构 调度器实例化 调度过程 触发器的获取 触发trigger: Job执行过程: 总结: 附: 引言 quratz是目前最为成 ...

  6. Quartz调度源码分析

    2019独角兽企业重金招聘Python工程师标准>>> 系列文章 Spring整合Quartz分布式调度 Quartz数据库表分析 Quartz调度源码分析 前言 上一篇文章Quar ...

  7. java quartz 重启不了_java – 重新启动quartz调度程序而不会出现错误

    上下文 我正在尝试使用jdbc在集群模式下使用quartz调度程序. 问题 在我开始使用集群模式的jdbc之前,我刚刚通过RAM存储测试了调度程序.这没有问题,我能够重启调度程序(主类),没有任何错误 ...

  8. quartz集群模式任务触发分析(二)

    前言 此处仅大致的将quartz的逻辑给理出来,有些具体的详细之处我也不是很清楚(苦笑) QuartzSchedulerThread quartzSchedulerThread是quartz的主线程, ...

  9. 一文揭秘定时任务调度框架quartz

    之前写过quartz或者引用过quartz的一些文章,有很多人给我发消息问quartz的相关问题, quartz 报错:java.lang.classNotFoundException quartz源 ...

  10. Quartz的定时任务实现

    Quartz中管理定时任务的Scheduler对应一个QuartzScheduler,其中,负责管理定时任务的线程QuartzSchedulerThread也在其构造方法中被启动. public Qu ...

最新文章

  1. Ret2Libc(2) (有system、无‘/bin/sh’)绕过NX、ASLR
  2. 归根到底,大家都是出来卖的!有的人月入十万,有的人月入三千!差距!
  3. 电商直播团队,管理好团队就成功了一半
  4. FlashDevelop+aswing开发AS2程序
  5. 完美的优化目标,人工智能的盲点
  6. r语言参数fig=c(),干货︱R语言绘图—基础图形参数整理
  7. ocp 043 第十三章:管理资源
  8. php 高级搜索下拉框,高级搜索页面advancedsearch.php调用自定义字段
  9. Guava入门~Lists
  10. js判断对象为空_在 JavaScript 中如何检查对象为空
  11. CNN——学习率LR的参考值范围是符合指数函数的增长规律的
  12. 剑指Offer——中国银行面试知识储备+面试内容(Offer-2已收割)
  13. LPVOID和PVOID的区别是什么
  14. JQuery注册登录
  15. Linux下查询外网IP地址方法集合
  16. vue设置浏览器顶部小图标
  17. 敏感字符的识别+处理
  18. 分享基于SpringBoot2+MybatiPlus+LayUI+Snaker+Mysql技术前后端分离开源后台管理系统脚手架
  19. jquery基础学习记录
  20. numpy之标准差std()

热门文章

  1. TBtools | 多图合一至强版教程!进化树 + Motifs + 结构域 + 启动子 + 基因结构 + ....
  2. 20182319彭淼迪第一周学习总结
  3. 好架构师都是写代码写出来的
  4. CSS - 选择器优先级介绍
  5. 电脑右键打印不见了_win7右键没有打印选项怎么办|右键菜单没有压缩选项怎么解决|右键没有图形选项解决方法-系统城...
  6. 3dmax学习笔记 (一)
  7. 解决octavia failed to run
  8. 【读书笔记】《早起的奇迹》
  9. Kindle通过邮箱传文件允许的文件类型。
  10. QGIS制作导出三维模型并发布