Quartz的misfire处理机制分析
Quartz是一个特性丰富的开源的任务调度开发库,它可以很方便的集成到你的应用程序中。在Quartz中,当一个持久的触发器因为调度器被关闭或者线程池中没有可用的线程而错过了激活时间时,就会发生激活失败(misfire)。那么,我们需要明确2个问题:如何判定激活失败;如何处理激活失败。
一、激活失败判定
quartz.properties配置文件中有一个属性是misfireThreshold(单位为毫秒),用来指定调度引擎设置触发器超时的"临界值"。也就是说Quartz对于任务的超时是有容忍度的,超过了这个容忍度才会判定misfire。比如说,某触发器设置为,10:15首次激活,然后每隔3秒激活一次,无限次重复。然而该任务每次运行需要10秒钟的时间。可见,每次任务的执行都会超时,那么究竟是否会引起misfire,就取决于misfireThreshold的值了。以第二次任务来说,它的运行时间已经比预定晚了7秒,那么如果misfireThreshold>7000,说明该偏差可容忍,则不算misfire,该任务立刻执行;如果misfireThreshold<=7000,则判定为misfire,根据相关配置策略进行处理。
注意,任务的延迟是有累计的。在前面的例子中,假设misfireThreshold设置为60000,即60秒。那么每次任务的延迟量即是否misfire计算如下:
任务编号 |
预定运行时刻 |
实际运行时刻 |
延迟量(秒) |
备注 |
1 |
10:15 |
10:15 |
0 |
|
2 |
10:18 |
10:25 |
7 |
|
3 |
10:21 |
10:35 |
14 |
|
4 |
10:24 |
10:45 |
21 |
|
5 |
10:27 |
10:55 |
28 |
|
6 |
10:30 |
11:05 |
35 |
|
7 |
10:33 |
11:15 |
42 |
|
8 |
10:36 |
11:25 |
49 |
|
9 |
10:39 |
11:35 |
56 |
|
10 |
10:42 |
11:45 |
63 |
misfire |
从表中可以看到,每一次任务执行都会带来7秒的延迟量,该延迟量不断被与misfireThreshold比较,直到达到该值后,在11:45分发生misfire。那么在11:45第10次任务会不会准时执行呢?答案是不一定,取决于配置。
二、激活失败处理
激活失败指令(Misfire Instructions)是触发器的一个重要属性,它指定了misfire发生时调度器应当如何处理。所有类型的触发器都有一个默认的指令,叫做Trigger.MISFIRE_INSTRUCTION_SMART_POLICY,但是这个这个“聪明策略”对于不同类型的触发器其具体行为是不同的。对于SimpleTrigger,这个“聪明策略”将根据触发器实例的状态和配置来决定其行为。具体如下[]:
如果Repeat Count=0:
instruction selected = MISFIRE_INSTRUCTION_FIRE_NOW;
如果Repeat Count=REPEAT_INDEFINITELY:
instruction selected = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
如果Repeat Count>0:
instruction selected = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;
下面解释SimpleTrigger常见策略:
MISFIRE_INSTRUCTION_FIRE_NOW
立刻执行。对于不会重复执行的任务,这是默认的处理策略。
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
NEXT指以现在为基准,以repeat interval为周期,延时到下一个激活点执行。WITH_REMAINING_COUNT指超时期内错过的执行机会作废。因此该策略的含义是,在下一个激活点执行,且超时期内错过的执行机会作废。
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_COUNT
立即执行,且超时期内错过的执行机会作废。
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
WITH_EXISTING_COUNT指,根据已设置的repeat count进行执行。也就是说错过的执行机会不作废,保证实际执行次数满足设置。因此本策略的含义是,在下一个激活点执行,并重复到指定的次数。
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_COUNT
立即执行,并重复到指定的次数。
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
忽略所有的超时状态,按照触发器的策略执行。
对于CronTrigger,该“聪明策略”默认选择MISFIRE_INSTRUCTION_FIRE_ONCE_NOW以指导其行为。
下面解释CronTrigger常见策略:
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
立刻执行一次,然后就按照正常的计划执行。
MISFIRE_INSTRUCTION_DO_NOTHING
目前不执行,然后就按照正常的计划执行。这意味着如果下次执行时间超过了end time,实际上就没有执行机会了。
三、示例程序1
=====代码=====
JobDetail job1 = newJob(StatefulDumbJob.class).withIdentity("statefulJob1", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build(); SimpleTrigger trigger1 = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()).build(); Date ft1 = sched.scheduleJob(job1, trigger1);
log.info(job1.getKey() + " will run at: " + ft1 + " and repeat: " + trigger1.getRepeatCount() + " times, every "
+ trigger1.getRepeatInterval() / 1000 + " seconds");
=====代码=====
misfireThreshold设置为60000。
分析:
各任务的延迟量如下表所示:
任务编号 |
预定运行时刻 |
实际运行时刻 |
延迟量(秒) |
备注 |
1 |
16:15:45 |
16:15:45 |
0 |
|
2 |
16:15:48 |
16:15:55 |
7 |
|
3 |
16:15:51 |
16:16:05 |
14 |
|
4 |
16:15:54 |
16:16:15 |
21 |
|
5 |
16:15:57 |
16:16:25 |
28 |
|
6 |
16:16:00 |
16:16:35 |
35 |
|
7 |
16:16:03 |
16:16:45 |
42 |
|
8 |
16:16:06 |
16:16:55 |
49 |
|
9 |
16:16:09 |
16:17:05 |
56 |
|
无 |
16:16:12 |
16:17:15 |
63 |
misfire |
10 |
16:17:18 |
16:17:18 |
0 |
|
11 |
16:17:21 |
16:17:28 |
7 |
在16:17:15发生misfire。因为Repeat Count=REPEAT_INDEFINITELY,所以smart policy选择的策略是MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT。因此,延时3秒后,在16:17:18第10次任务被执行,延迟量清零。当然,程序会一直这样循环下去。
程序输出:
---group1.statefulJob1 executing.[Fri Feb 19 16:15:45 CST 2016]
-group1.statefulJob1 complete (1).
---group1.statefulJob1 executing.[Fri Feb 19 16:15:55 CST 2016]
-group1.statefulJob1 complete (2).
---group1.statefulJob1 executing.[Fri Feb 19 16:16:05 CST 2016]
-group1.statefulJob1 complete (3).
---group1.statefulJob1 executing.[Fri Feb 19 16:16:15 CST 2016]
-group1.statefulJob1 complete (4).
---group1.statefulJob1 executing.[Fri Feb 19 16:16:25 CST 2016]
-group1.statefulJob1 complete (5).
---group1.statefulJob1 executing.[Fri Feb 19 16:16:35 CST 2016]
-group1.statefulJob1 complete (6).
---group1.statefulJob1 executing.[Fri Feb 19 16:16:45 CST 2016]
-group1.statefulJob1 complete (7).
---group1.statefulJob1 executing.[Fri Feb 19 16:16:55 CST 2016]
-group1.statefulJob1 complete (8).
---group1.statefulJob1 executing.[Fri Feb 19 16:17:05 CST 2016]
-group1.statefulJob1 complete (9).
---group1.statefulJob1 executing.[Fri Feb 19 16:17:18 CST 2016]
-group1.statefulJob1 complete (10).
四、示例程序2
=====代码=====
JobDetail job2 = newJob(StatefulDumbJob.class).withIdentity("statefulJob2", "group1")
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L).build(); SimpleTrigger trigger2 = newTrigger()
.withIdentity("trigger2", "group1")
.startAt(startTime)
.withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever()
.withMisfireHandlingInstructionNowWithExistingCount()) // set misfire instructions
.build(); Date ft2 = sched.scheduleJob(job2, trigger2);
log.info(job2.getKey() + " will run at: " + ft2 + " and repeat: " + trigger2.getRepeatCount() + " times, every "
+ trigger2.getRepeatInterval() / 1000 + " seconds");
=====代码=====
misfireThreshold设置为60000。
分析:
示例2与示例1的区别在于,触发器指定了激活失败指令为MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_COUNT。
各任务的延迟量如下表所示:
任务编号 |
预定运行时刻 |
实际运行时刻 |
延迟量(秒) |
备注 |
1 |
17:05:15 |
17:05:15 |
0 |
|
2 |
17:05:18 |
17:05:25 |
7 |
|
3 |
17:05:21 |
17:05:35 |
14 |
|
4 |
17:05:24 |
17:05:45 |
21 |
|
5 |
17:05:27 |
17:05:55 |
28 |
|
6 |
17:05:30 |
17:06:05 |
35 |
|
7 |
17:05:33 |
17:06:15 |
42 |
|
8 |
17:05:36 |
17:06:25 |
49 |
|
9 |
17:05:39 |
17:06:35 |
56 |
|
无 |
17:05:42 |
17:06:45 |
63 |
misfire |
10 |
17:06:45 |
17:06:45 |
0 |
|
11 |
17:05:48 |
17:06:55 |
7 |
在17:06:45发生misfire。根据其激活失败指令,任务10在该时刻被立即执行,延迟量清零。然后,程序继续如此循环下去。
程序输出:
---group1.statefulJob2 executing.[Fri Feb 19 17:05:15 CST 2016]
-group1.statefulJob2 complete (1).
---group1.statefulJob2 executing.[Fri Feb 19 17:05:25 CST 2016]
-group1.statefulJob2 complete (2).
---group1.statefulJob2 executing.[Fri Feb 19 17:05:35 CST 2016]
-group1.statefulJob2 complete (3).
---group1.statefulJob2 executing.[Fri Feb 19 17:05:45 CST 2016]
-group1.statefulJob2 complete (4).
---group1.statefulJob2 executing.[Fri Feb 19 17:05:55 CST 2016]
-group1.statefulJob2 complete (5).
---group1.statefulJob2 executing.[Fri Feb 19 17:06:05 CST 2016]
-group1.statefulJob2 complete (6).
---group1.statefulJob2 executing.[Fri Feb 19 17:06:15 CST 2016]
-group1.statefulJob2 complete (7).
---group1.statefulJob2 executing.[Fri Feb 19 17:06:25 CST 2016]
-group1.statefulJob2 complete (8).
---group1.statefulJob2 executing.[Fri Feb 19 17:06:35 CST 2016]
-group1.statefulJob2 complete (9).
---group1.statefulJob2 executing.[Fri Feb 19 17:06:45 CST 2016]
-group1.statefulJob2 complete (10).
---group1.statefulJob2 executing.[Fri Feb 19 17:06:55 CST 2016]
-group1.statefulJob2 complete (11).
Quartz的misfire处理机制分析的更多相关文章
- quartz群调查调度机制和源代码分析
pageId=85056282#quartz集群调度机制调研及源代码分析-quartz2.2.1集群调度机制调研及源代码分析" style="color:rgb(59,115,17 ...
- Linux mips64r2 PCI中断路由机制分析
Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...
- IOS Table中Cell的重用reuse机制分析
IOS Table中Cell的重用reuse机制分析 技术交流新QQ群:414971585 创建UITableViewController子类的实例后,IDE生成的代码中有如下段落: - (UITab ...
- 您还有心跳吗?超时机制分析(java)
注:本人是原作者,首发于并发编程网(您还有心跳吗?超时机制分析),此文结合那里的留言作了一些修改. 问题描述 在C/S模式中,有时我们会长时间保持一个连接,以避免频繁地建立连接,但同时,一般会有一个超 ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- Linux信号(signal) 机制分析
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
- Java 动态代理机制分析及扩展
Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...
- Quartz的misfire特性
Quartz的misfire特性 只有一个线程.多个job 第一个job产生misfire(executeTime>Interval) 且是repeatForever 那么只会运行第一个job, ...
- Android内存机制分析1——了解Android堆和栈
//----------------------------------------------------------------------------------- Android内存机制分析1 ...
随机推荐
- noip冲刺赛第五次考试
1.公约数 (gcd.cpp\c\pas) [问题描述] 给定一个正整数,在[1,n]的范围内,求出有多少个无序数对(a,b)满足 gcd(a,b)=a xor b. [输入格式] 输入共一行,一个正 ...
- BPM与OA的区别及联系
BPM与OA的区别及联系 近年来,在企业管理信息系统一些名词反复被提及,然而外行人对于这些名词则是一头雾水,网上的解释又鱼龙混杂,没有绝对权威的文献可供参考,因此也就让我们对这些名词的认识越来越模糊. ...
- Luogu P2966 [USACO09DEC]牛收费路径Cow Toll Paths
题目描述 Like everyone else, FJ is always thinking up ways to increase his revenue. To this end, he has ...
- ES6新特性之生成器函数 (generator function): function*
一.什么是生成器函数(generator function)? 生成器函数是ES6的新特性之一,它是一个在执行时能中途暂时退出,后面重新调用又能重新进入继续执行的一种函数. 并且在函数内定义的变量的所 ...
- Python使用PDFMiner解析PDF
近期在做爬虫时有时会遇到网站只提供pdf的情况,这样就不能使用scrapy直接抓取页面内容了,只能通过解析PDF的方式处理,目前的解决方案大致只有pyPDF和PDFMiner.因为据说PDFMiner ...
- xhost和DISPLAY
xhost是用来控制X server访问权限的. 通常当你从hostA登陆到hostB上运行hostB上的应用程序时,做为应用程序来说,hostA是client,但是作为图形来说,是在hostA上显示 ...
- 两点补充——CSS3新属性以及弹性布局
CSS3 新属性 一.[ CSS3新增属性前缀 ] 1.-webkit-:chrome/safari 2.-moz-:火狐 3.-mo-:IE 4.-o-: Opera 欧朋 二 .[CSS 长度单位 ...
- 整理pandas操作
本文原创,转载请标识出处: http://www.cnblogs.com/xiaoxuebiye/p/7223774.html 导入数据: pd.read_csv(filename):从CSV文件导入 ...
- CSS常见英语单词属性一览
这些是css中常会用到的一些英文单词,大家可以多看看,多使用就会容易记得了. color : #999999; /*文字颜色*/ font-family : 宋体,sans-serif; /*文字字体 ...
- Fiddler过滤会话
Fiddler每次打开的时候都会打开十多个会话,期望只想抓取自己想要的请求. 1)User Filters:启用过滤器 2)在Filers面板中勾选"Use Filters", ...