• org.quartz.impl.jdbcjobstore.JobStoreSupport recoverMisfiredJobs


    一月 21, 2022 7:23:27 上午 org.quartz.impl.jdbcjobstore.JobStoreSupport recoverMisfiredJobs
    信息: Handling 5 trigger(s) that missed their scheduled fire-time.

    有时候Quartz并不能如你所愿的运行你的job。这里有3个原因:
    1.所有的woker thread(工作线程; 辅助线程)都在运行其他的job
    2.scheduler(调度器)down了(关于这个down。我不太明确是shutdown了。。还是挂掉了。因此下文依旧用down。)

    3.任务被安排在过去的某一时刻启动(此可能为代码错误) 


    你可以简单地通过配置quartz.properties文件中的org.quartz.threadPool.threadCount这方法仍然是无效的。这种Quartz无法启动指定触发器情况汉语无法贴切表达)。
    你知道当这种情况发生的时候Quartz有许多的策略(叫misfire instructions并且当你没有去想这方面问题的时候你应该有意识的去确保triggers 和 jobs工作正常。

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

    在我深入细节之前默认是60000(一分钟)。它定义了

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

    然而当延迟了61秒时misfire handler thread)”就会按照misfire instructions去处理它了。

    为了测试效果这样就能很快的测试“失火”了。


    第一个例子triggertrigger调度器是怎么处理“失火”Simple scheduled to run only once:】

    1.val 2.startAt(DateUtils.addSeconds(new Date()10)).
    3.build()

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

    1.val 2.startAt(DateUtils.addSeconds(new Date()10)).
    3.withSchedule(
    4.simpleSchedule().
    withMisfireHandlingInstructionFireNow() //MISFIRE_INSTRUCTION_ 6.).
    7.build()

    为了测试trigger设置为10秒前被调度(即当创建后我们基本上永远不会这么设置。

    换句话说trigger调度器down了或者没有空闲的worker thread了。那么extraordinary(罕见没有设置misfire instruction(so called smart policy is used in 第二段代码中我们希望采取的行为。

    来看下表:

    指令 Instruction 意义 Meaning
    smart policy - default See: withMisfireHandlingInstructionFireNow
    withMisfireHandlingInstructionFireNow
    MISFIRE_INSTRUCTION_调度器发现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被忽略了可以使用这个指令。
    例如:
    2个小时候才发现。  
    【PS: 这个不是太理解如果要用withMisfireHandlingInstructionNowWithExistingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
    See: withMisfireHandlingInstructionFireNow
    withMisfireHandlingInstructionNowWithRemainingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
    See: withMisfireHandlingInstructionFireNow



    普通我们有一些需要重复执行指定次数的job:

    01.val 02.startAt(dateOf(900)).
    03.withSchedule(
    04.simpleSchedule().
    0withRepeatCount(7).
    06.withIntervalInHours(1).
    07.WithMisfireHandlingInstructionFireNow()  //or other
    08.).
    09.build()

    在这个例子中trigger从今天9点开始(startAt(dateOf(9, 0))和7次重复)。

    按理在9点和10点调度器没有执行job5才被系统发现misfire调度器会怎么样呢?

    指令 Instruction 意义 Meaning
    smart policy - default See:withMisfireHandlingInstructionNowWithExistingCount
    withMisfireHandlingInstructionFireNow
    MISFIRE_INSTRUCTION_See:withMisfireHandlingInstructionNowWithRemainingCount
    withMisfireHandlingInstructionIgnoreMisfires
    MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
    尽快启动所有被启动的并将调度置为正常。
    例如:
    在我们上面的例子中并等待11点时 备注:当处理misfire时实际job执行的时间你不能简单地的依赖当前系统时间而是应该使用 JobExecutionContext .getScheduledFireTime()去获取。
    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点1继续执行共执行8次调度操作withMisfireHandlingInstructionNextWithRemainingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
    调度器会抛弃被misfire的操作执行的总次数5然后继续触发其余的直到4点。事实上withMisfireHandlingInstructionNowWithExistingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
    第一次misfire的而后会按设置的间隔trigger。实际上trigger的第一次触发时间5第一次运行misfire的然后隔1个小时5执行第二次。共执行8次在下午5

    withMisfireHandlingInstructionNowWithRemainingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT

    第一次misfire的操作会被抛弃。
    剩余没有被misfire的会按固定间隔被触发。
    例如:
    调度器会在10点1它抛弃其余被misfire的(10点那一次)。最后trigger
    11:1,12:15 PM。



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

    01.val 02.startAt(dateOf(900)).
    03.withSchedule(
    04.simpleSchedule().
    0withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY).
    06.withIntervalInHours(1).
    07.WithMisfireHandlingInstructionFireNow()  //or other
    08.).
    09.build()

    , 0每隔小时触发一次。然而调度器在9点到10点都没有执行job(比如关闭了系统、线程不够等等。。前面有介绍)5时才被发现trigger更加普遍。

     

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

    withMisfireHandlingInstructionNextWithExistingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
    See:withMisfireHandlingInstructionNextWithRemainingCount
    withMisfireHandlingInstructionNextWithRemainingCount
    MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
    不做任何事情调度器按设置的间隔等待下次执行。
    例如:
    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点1trigger在11点1执行第二次。以后会每隔一小时。


    定时触发    CRON 定时触发是Quartz中最常见的。它有另外两个有效的DailyTimeIntervalTrigger(比如每2CalendarIntervalTrigger(比如但是他们和CRON 支持同样的misfire

    1.val 2.withSchedule(
    3.cronSchedule("0 0 9-17 ? * MON-FRI").
    4.withMisfireHandlingInstructionFireAndProceed()  //or other
    ).
    6.build()

    这个例子是trigger在每周一到周五的早上9点到下午每小时被触发一次。但是两次触发被misfire了5他们的失火指令效果与普通

    指令 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个)被立即执行withMisfireHandlingInstructionFireAndProceed
    MISFIRE_INSTRUCTION_
    立即执行第一次misfire的操作trigger的执行10点需要执行的那次withMisfireHandlingInstructionDoNothing
    MISFIRE_INSTRUCTION_DO_NOTHING
    所有被misfire的执行都被忽略掉好像什么都没发生一样。下次执行将在11点被执行。
       

    QTZ-283NoteQTZ-283: MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY not working with JDBCJobStore - apparently there is a bug when JDBCJobStore is usedthat issue. (在用JDBCJobStore 时MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 没有生效。显然JDBCJobStore时的一个bug

    如你所有不同的虽然它提供了smart policy(明智的决策)还是要取决于业务需求。

    从本质上看立即运行然后继续正常执行ignorerun immediately and continue and discard and wait for next. )

    它们有不同的应用场景:

    当你需要确保每次调度任务都要被执行的时候trigger会被触发ignore policies。试想一下需要每小时那你可能仍然是尽快得到那些报表的。这种情况下ignore policies但是仍然是被执行了(最终报告到手了。^_^)。

    当你需要任务被定期执行那么使用now* policies。试想一下最后终于可以执行这个任务了但是要尽快执行。而后使用next* policies不错。比如你需要在每个整点后1然后现在已经整点后20分了5分钟一个时间间隙总好过一个不准确的值。这种情况Quartz只要跳过misfire的操作等待下次执行就好了。

  • 相关阅读:
    JAVA操作数据库 http://blog.sina.com.cn/andyfang
    JSP连接各类数据库大全
    Jigloo 开发 SWT 的入门教程
    kv离线升级
    MySQL内存表的弊端
    MySQL中Order By实现原理分析
    Linux安装性能问题
    按照经纬度实现位置计算
    NOSQL数据模型和CAP原理
    C语言 side effect 和 sequence point
  • 原文地址:https://www.cnblogs.com/interdrp/p/15828842.html
Copyright © 2020-2023  润新知