我的日常

登录/注册
您现在的位置:论坛 盖世程序员(我猜到了开头 却没有猜到结局) 盖世程序员 > missed their scheduled fire-time
总共48086条微博

动态微博

查看: 3540|回复: 0

missed their scheduled fire-time

[复制链接]

114

主题

29

听众

429

金钱

传功长老

该用户从未签到

跳转到指定楼层
楼主
发表于 2014-07-08 21:08:58 |只看该作者 |倒序浏览
如果你在用quartz的时候,也看到这个日志信息(Handling 2 trigger(s) that missed their scheduled fire-time.)了,并且发现quartz管理的任务,都不再被触发了,那么,你可以看看这篇文章。
6 h4 W7 Z7 z7 j! W. ]0 f. B
2 t6 B# d' b+ |0 a原文地址: http://java.dzone.com/articles/quartz-scheduler-misfire" S6 w2 M% I2 [9 Z) X
由于本人英文水平有限,部分地方会直接用原文英语代替,另,部分翻译可能比较晦涩,望理解。
2 |9 q* e! ^9 a+ i9 H6 R, J  v- P- P+ }9 i) G- p& J0 f
常见词:
6 s" v  X# t# Hmisfire  http://fanyi.baidu.com/#en/zh/misfire 以下统一用misfire,汉语无法贴切表达 7 g" _  }6 c8 I5 D% o  `7 K2 p, d
misfire instruction 失火(没启动起来后的)指示
% F$ `. C, N1 c# }6 jsmart policy,明智的决策0 e; f- y& I- S5 e5 p
misfired 失火了,没启动起来的意思. U- ?) i! y# Q- l  N) O% `) ^/ _2 P
worker thread 工作线程,辅助线程
% L* r1 J4 \4 Y5 o  k, z: Q# `
# V. i! a5 S/ x【翻译】
+ c3 V3 B$ D+ v有时候,Quartz并不能如你所愿的运行你的job。这里有3个原因:
/ a' D7 g6 s- Y) {1.所有的woker thread(工作线程; 辅助线程)都在运行其他的job
8 S9 d/ w  ], {$ w4 i7 U# e2.scheduler(调度器)down了(关于这个down。我不太明确是shutdown了。。还是挂掉了。因此下文依旧用down。)
, }6 y# U: v/ [! C( B3.任务被安排在过去的某一时刻启动(此可能为代码错误). x. t5 _/ M" H; l

: X3 G& o; I7 q% c# d, D你可以简单地通过配置quartz.properties文件中的org.quartz.threadPool.threadCount,来增加worker thread的数量(默认为10)。但是当整个 applicationfile:///C:\Users\user\AppData\Local\Temp\V7(XMWRN]{G8~CI}BCCR3QC.gifrver/scheduler (调度器)挂掉的时候,这方法仍然是无效的。这种Quartz无法启动指定触发器情况,叫做 misfire(http://fanyi.baidu.com/#en/zh/misfire 以下统一用misfire,汉语无法贴切表达)。$ P3 C. S5 M) K0 c: ]* q- X  y
你知道当这种情况发生的时候,Quartz能做些什么吗? 其实,Quartz有许多的策略(叫misfire instructions,失火指示)可以处理问题,并且当你没有去想这方面问题的时候,它也有许多默认策略。但是为了使你的应用更加稳定和可预测(尤其是在高负载和可维护性上),你应该有意识的去确保triggers 和 jobs工作正常。; V$ v5 \  \3 w: s* t1 b# {
基于你用的trigger,会有不同的配置选项(对misfire instructions有效)。当然,不同的trigger也会使Quartz有不同的行为(叫做smart policy,明智的决策)。尽管文档中有misfire instructions的描述,但是我发现都很难理解它所想表达的意思,因此,我写下这篇简短的总结。
9 V" @1 [$ y8 p* r. k: [8 g8 [/ C1 x在我深入细节之前,还有一个配置需要说明下:org.quartz.jobStore.misfireThreshold(毫秒级),默认是60000(一分钟)。它定义了trigger被认为是misfired了的时限。1 X3 |9 q) i3 ]" H
基于默认配置,如果trigger应该在30秒以前被触发,那么很愉快地,Quartz就把它搞定了。这种延迟(delay)不能叫失火。
0 R/ U  e, r* x( z然而当trigger被发现,延迟了61秒时,那么专门的“失火处理者(misfire handler thread)”就会按照misfire instructions去处理它了。
4 }$ s8 w# J: c6 r# x$ a为了测试效果,我们将这个时间设置为1000(即1秒),这样就能很快的测试“失火”了。
& n! W7 {3 G( Z, O2 h; @8 }; ]3 l# c3 I: k% d  C( ]4 P

5 ^5 U' f- s0 U# G) _第一个例子,是一个不需要重复触发的普通trigger,我们来看看普通trigger调度器是怎么处理“失火”,并让它运行一次的:
8 }* [' ?* I3 q' \8 o【原文:Simple trigger without repeating In our first example we will see how misfiring is handled by simple triggers scheduled to run only once:】4 s+ G% f8 ]& }! n0 q  W8 ^/ r, P+ Z- ]
view sourceprint?
' {7 w! C0 q. [; w5 o5 x  k1.val trigger = newTrigger()./ ]$ j5 C$ y1 i: b
2.startAt(DateUtils.addSeconds(new Date(), -10)).
' o5 f9 }; o9 M+ J( \3.build()
4 M+ T. f# N! M$ g* D" M$ G9 V0 k) j" T
# O8 e6 u, z. H  t1 B2 {! p
同样的trigger,但是明确设置了misfire instruction handler(失火处理者):
3 Y( Y' \9 c$ [9 i, ~! v6 M. Pview sourceprint?, S% s& X* I0 d+ }
1.val trigger = newTrigger().
$ Z  w2 g% q# e! L2.startAt(DateUtils.addSeconds(new Date(), -10)).6 i! _( b6 y2 d' O
3.withSchedule(, Z& I3 b: s& ], J7 y( ^  b
4.simpleSchedule().
2 p  t+ `" B, j5.withMisfireHandlingInstructionFireNow() //MISFIRE_INSTRUCTION_FIRE_NOW9 N- |0 l& n" ]  E& H4 i
6.).
$ |* P+ n6 ^+ W7 I7.build()* c9 D8 ~/ E* |& X
; S& z6 W3 K0 I

8 @1 X8 v7 D, r) W+ T; u为了测试,我将trigger设置为10秒前被调度(即当创建后,就已经晚于启动时间10秒)。在实际使用时,我们基本上永远不会这么设置。2 X  @' \/ o8 J* \" A
换句话说,如果我们正确的设置了trigger,但是当需要被调度的时候,调度器down了或者没有空闲的worker thread了。那么,Quartz怎么处理这种extraordinary(罕见,古怪)的情况呢?$ T6 V# J8 }3 D  H4 p" ~
在第一段代码中,没有设置misfire instruction(so called smart policy is used in that case 这句不太会翻译。。。。)。) v: G2 Z* N, _
第二段代码中,明确指定了当misfire发生时,我们希望采取的行为。
0 a) k8 \- d7 s% t- ~来看下表:
. \6 f& t, _' s) f3 e2 |1 @' Z9 L, m/ }' o7 l3 k# T
指令 Instruction        意义 Meaning
# ^* t1 H2 O  C( _, \smart policy - default        See: withMisfireHandlingInstructionFireNow! i: r. n/ ]2 O/ v
withMisfireHandlingInstructionFireNow
# P3 R3 K# d: A/ KMISFIRE_INSTRUCTION_FIRE_NOW        调度器发现misfire情况后,立即执行job。
/ y& {9 ?4 P6 R" V: g: A这是smart policy。" e% Q3 i8 p& a; ~0 I
例如:
9 }7 Q8 [: ^: y8 _3 _1 r. @# B8 a你让一些系统清理功能在2点执行。但是很不幸,应用在那段时间由于维护,关闭了,直到3点才恢复。这样trigger就misfire了,然后调度器会尝试修复这种情况,在3点启动后,尽快执行。
, @; M+ P6 K4 N4 ?% ]8 j" TwithMisfireHandlingInstructionIgnoreMisfires
2 _2 |3 ?9 \& m* @! B1 ]3 PMISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY        See: withMisfireHandlingInstructionFireNow
/ E5 x  j; C5 G+ f, q% q) Y1 twithMisfireHandlingInstructionNextWithExistingCount* m; W# ?2 `' ?% i7 ?* I
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT        See: withMisfireHandlingInstructionNextWithRemainingCount7 v4 N2 e2 D( B- ]; u' s0 P
withMisfireHandlingInstructionNextWithRemainingCount
* L6 j3 B$ r0 \+ DMISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT        什么都不做。misfire被忽略了,并且没有后续的执行。当你想要彻底放弃被misfire的执行时,可以使用这个指令。
+ G& [  {5 p+ ~2 `4 v例如:, s& h9 Q4 ^3 @4 p+ p3 w+ |
trigger是要启动录制一个电视节目。但是被misfire了,2个小时候,才发现。  
' C& g3 x/ w: X6 G" U) w【PS: 这个不是太理解,只是按照原文翻译过来,如果要用,请自行测试。。。】
4 X6 \3 K$ {6 {8 c% Y8 a: m3 KwithMisfireHandlingInstructionNowWithExistingCount
4 \& M  g- N; nMISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT        See: withMisfireHandlingInstructionFireNow
  X0 Y2 p$ F" a6 Q  z0 ywithMisfireHandlingInstructionNowWithRemainingCount
4 L; e* c7 R7 P. s! _MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT        See: withMisfireHandlingInstructionFireNow7 ?/ G& X3 m7 E
( v3 O  H. a, @) _3 S, [
1 l9 O  e+ O0 Q
普通trigger重复执行指定次数。这种情形更加复杂。想象一下,我们有一些需要重复执行指定次数的job:, \6 H! i' F- D' G" c
view sourceprint?
2 u( t) P7 Y/ q# f' ?01.val trigger = newTrigger().
+ E& z: h3 l' q8 r3 C; B02.startAt(dateOf(9, 0, 0)).
5 @' ]7 |0 U9 ?( G03.withSchedule(
  L8 B. W$ G" O9 C7 W! c04.simpleSchedule()." K3 @- n: f$ k& c" P7 t
05.withRepeatCount(7)., v, Z9 b# V4 B3 K4 a  G! i% E
06.withIntervalInHours(1).$ |! B! b4 S% ~( F3 y) s$ f2 {0 S
07.WithMisfireHandlingInstructionFireNow()  //or other
7 {! V* L0 c5 g& {08.).
: o- }) ]' c9 G$ l09.build()5 o/ \4 c- T$ [% o1 o

% W$ {# y. h% a4 D, F% O8 E1 }( ]& A  z& [0 {7 ~
在这个例子中,trigger从今天9点开始(startAt(dateOf(9, 0, 0)),共触发8次(第一次执行,和7次重复)。" o: G5 ]: {: u4 K7 }4 E. t1 Z
按理,最后一次执行应该在下午4点被触发。假设由于某些原因,在9点和10点调度器没有执行job,并且直到10:15才被系统发现misfire,也就是misfire了2次。这种情况下,调度器会怎么样呢?
1 o( |0 v. t1 [+ x0 V指令 Instruction        意义 Meaning( r3 q; h' A0 I7 t4 D: `, D
smart policy - default        See:withMisfireHandlingInstructionNowWithExistingCount) ?# e- Q5 ~7 ]5 r! ^$ b/ @; X) A5 p
withMisfireHandlingInstructionFireNow: |0 `3 Z2 e$ \: r
MISFIRE_INSTRUCTION_FIRE_NOW        See:withMisfireHandlingInstructionNowWithRemainingCount
' i9 f& X! s+ v3 j" hwithMisfireHandlingInstructionIgnoreMisfires, B$ ?8 }9 I3 V" M5 s
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY        尽快启动所有被启动的trigger,并将调度置为正常。
6 R0 d7 W" P/ B# s2 v" x! C例如:
/ j0 G' Y  a2 n. \. Q8 \, \+ O  P在我们上面的例子中,调度器会立即执行9点和10点的任务,并等待11点时,继续按正常的调度执行。
: A' c; z+ \; l" c( n- y/ Y- x4 J备注:当处理misfire时,我们同样要注意到,实际job执行的时间,已经滞后于应该执行的时间。这意味着,你不能简单地的依赖当前系统时间,而是应该使用 JobExecutionContext .getScheduledFireTime()去获取。
! }  b; R* a/ B- Eview sourceprint?' q! q2 Y. f1 f: z& X# O1 e, i) S
1.def execute(context: JobExecutionContext) {
0 j8 N7 F; f5 i8 `+ @2.val date = context.getScheduledFireTime
- }) R$ o; q$ q3.//...
9 z; a/ ^+ b& n# P7 B1 i; I4.}
: |( H9 \4 Z9 x' Y3 j* ?: `3 `* t7 h. t; L* p

$ @1 a! @+ a$ rwithMisfireHandlingInstructionNextWithExistingCount% Z- j/ W5 @# }- w
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT        调度器不会马上有反应。它会等待下一次执行,然后根据应该调度次数去运行trigger。6 Q" T7 I4 V: K4 T7 X
See also: withMisfireHandlingInstructionNextWithRemainingCount
! w  i( d5 A  a: r) h; [例如:
# `) D$ z0 Z) w0 i( X1 N在10点15发现2次misfire。调度器会等到11点,继续执行,并会每小时执行1次,共执行8次调度操作,直到下午6点停止(本该4点停止的。)( A+ D$ i3 a% v% W" c
withMisfireHandlingInstructionNextWithRemainingCount
" j9 M6 B7 m! w5 g1 ~MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT        调度器会抛弃被misfire的操作,然后等待下次执行。这样,执行的总次数,就会小于配置的次数。/ Y  X/ u% Y' a) V
例如:在10点15,2次misfire的执行都被丢弃了。调度器会等到下个执行时间-11点,然后继续触发其余的trigger,直到4点。事实上,这种情况就像misfire从未发生过一样。
" b4 w/ N8 R! A) x% x! ^2 T2 zwithMisfireHandlingInstructionNowWithExistingCount, w  ~7 ?& m1 V% e/ _: g- N  F4 ~, U
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT1 P6 Q2 h4 R" m. _. k  L/ u5 T
第一次misfire的trigger会立即执行,而后会按设置的间隔,依次执行剩余的trigger。实际上,就像misfire的trigger的第一次触发时间,被平移到了当前时间。
! H5 r: E. b+ {0 @8 B/ ~0 ]例如:, m0 c+ Y; K2 Q3 l" p6 G
调度器会在10点15第一次运行misfire的trigger,然后隔1个小时,在11点15执行第二次。共执行8次,最后一次,在下午5点15。
# i, z( z9 C% s) G, Z5 O+ S  Y+ U/ i4 T/ u
withMisfireHandlingInstructionNowWithRemainingCount' Y' j  P6 o3 w/ D- F% Z% @2 |5 J
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT          A/ ~! Y- k% a* ]: ]
第一次misfire的操作,被立即执行。其余被misfire的操作,会被抛弃。
2 ^) K, C+ E- y6 S# |# f" r$ b% W! c剩余没有被misfire的trigger,会按固定间隔被触发。
' l6 i! y  n6 j* s例如:9 O" K) O4 H/ @  f3 s
调度器会在10点15运行第一次被misfire的操作(9点的。)。然后,它抛弃其余被misfire的(10点那一次)。最后,它会等1小时继续触发6个trigger:0 O: ]$ X' x" {1 F! r
11:15,12:15.... 4:15 PM。
* ?4 _, a$ i0 r1 U! x$ Z6 E; ?  ?/ ?, [: Y
$ _% y5 I) P. Q) }  i& ^( h, G
这是一个基于指定间隔、并重复无数次的trigger:
$ a+ Y! U+ R' [( Dview sourceprint?0 L6 W1 J+ M0 p* F' F
01.val trigger = newTrigger().
3 y% [2 w7 C1 W( Q) N: z/ E2 h7 Q02.startAt(dateOf(9, 0, 0)).. W" b4 C$ l! j: j0 s
03.withSchedule(
) Y3 i$ \6 G! p1 u' B0 u% _04.simpleSchedule().% i, b- Z7 {, I5 ~5 D0 r2 d7 I
05.withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY).- \: l# o, S  r6 o' f% N1 n
06.withIntervalInHours(1).8 N% y( L  A3 j
07.WithMisfireHandlingInstructionFireNow()  //or other
: A  B5 p! ~  l08.).+ ?/ O0 a5 R4 h% r
09.build()
/ g/ g+ Q7 ?: [: V; \9 `
* C) N5 |( R* Q. R$ N* C; O/ ?+ r
7 o- d2 a& A/ o( L3 D4 utrigger应该从今天9点开始(startAt(dateOf(9, 0, 0)),每隔小时触发一次。然而调度器在9点到10点都没有执行job(比如关闭了系统、线程不够等等。。前面有介绍),并且在10点15时才被发现,misfire了2次。这种情况比那种执行执行次数的trigger更加普遍。" G2 m8 c8 q& t
指令 Instruction        意义 Meaning$ S% u% r9 j; |: z5 ]! F' s" u  {8 W
smart policy - default        See:withMisfireHandlingInstructionNowWithExistingCount# z# t! g2 c6 f
withMisfireHandlingInstructionFireNow
5 _5 w) I; `2 x' XMISFIRE_INSTRUCTION_FIRE_NOW        See: withMisfireHandlingInstructionNowWithRemainingCount
9 `1 f  x, t: R: z+ PwithMisfireHandlingInstructionIgnoreMisfires
. ^' S2 I# ~4 g! ~MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY# q5 {; z# v6 X0 ~' r
https://jira.terracotta.org/jira/browse/QTZ-283, v% q! |3 e* ~6 L+ e) R6 o- O
调度器会立即执行所有misfire的trigger,然后继续正常调度。- {. j) X% \1 D! C9 f. e
例如:
9 J9 u6 K( m; B' h9点和10点的trigger会立即执行,下次执行将按计划执行(下一次是11点执行)。
  V  a5 M6 h  T, K3 {* D/ a. ~. M% _" a, `5 ~4 Q8 f* I, U
withMisfireHandlingInstructionNextWithExistingCount
; b8 |( e9 c  v% z, m% U4 B7 |, e$ |6 xMISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT        See:withMisfireHandlingInstructionNextWithRemainingCount! N7 o1 O% d3 _
withMisfireHandlingInstructionNextWithRemainingCount
0 k+ E# _! i. ~9 N; sMISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT: I- f" u& V4 }; d/ x$ y" I/ ^
不做任何事情,misfire的情况被忽略掉。然后,调度器按设置的间隔等待下次执行。. \6 f0 g8 {) h" |* m1 a' |/ Q
例如:8 ~5 X- g8 |8 `+ ^
9点和10点misfire的执行被忽略掉。第一次执行会在11点会开始。
+ l& i. x& y5 O% P- kExample scenario: Misfired execution at 9 and 10 AM are discarded. The first execution occurs at 11 AM.9 K* y: B3 N5 O+ o

7 C: j. u+ M% G) N  A; nwithMisfireHandlingInstructionNowWithExistingCount
$ e' N- q; ?+ a" A  MMISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
8 |0 E" m9 v9 ]8 {See:withMisfireHandlingInstructionNowWithRemainingCount
4 y4 W% _' J* V- ^* ?! zwithMisfireHandlingInstructionNowWithRemainingCount& r  S: T6 [$ A" V( F
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
* A- M/ t1 z! @! o: f! F
, A6 r$ ~$ k0 V* {- ^
2 |8 R8 _  m8 p6 n+ h第一次misfire的执行会被立即运行,其余的被忽略。下次执行会在设置的间隔时间后被触发。实际上,就是第一次执行被推迟到了当前时间。! Q+ n( [# o, I1 m2 g% E
例如:& Y, u* l; M& k/ o8 x
调度器在10点15立即执行misfire的trigger,然后等待一个小时后,在11点15时,执行第二次。以后会每隔一小时。
1 @4 R* K( j6 [+ `; @: [! Q
1 S' T( h* V( E* ?& L( D) N& P' V- a  q$ J9 {/ ~
定时触发    CRON trigger' t' R8 N/ K$ B* q2 Q" z& D
定时触发是Quartz中最常见的。它有另外两个有效的trigger:DailyTimeIntervalTrigger(比如每25分钟一次)和CalendarIntervalTrigger(比如5个月执行一次)。They support triggering policies not possible in both CRON and simple triggers.(不会译- -!),但是他们和CRON trigger一样,支持同样的misfire handling instructions(失火处理指令)。2 X% Q" J; `4 C4 m- A. k
view sourceprint?. J. I( r% l9 j$ \1 a
1.val trigger = newTrigger().
1 k' N" I! ]2 R/ i" F  N2.withSchedule(. p; h0 d$ A1 i& Q6 W, |" N
3.cronSchedule("0 0 9-17 ? * MON-FRI").# ^9 B6 A+ n% O9 l1 x
4.withMisfireHandlingInstructionFireAndProceed()  //or other" j# t  K; u9 b% T
5.).2 M  {- L( k# i+ F4 t9 s, d- M
6.build()  b! W/ M( Q1 H8 n, Y! F
2 z9 l5 X9 K3 {' G5 @- [

" x+ f- k8 i/ b- V; o, H) K这个例子是,trigger在每周一到周五的早上9点到下午5点间,每小时被触发一次。但是两次触发被misfire了,并且在10点15时,才发现这个情况。请注意,他们的失火指令效果与普通trigger是不同的:
; B: B/ @, O8 a, N# N指令 Instruction        意义 Meaning4 n2 H6 V+ n2 G6 _* c
smart policy - default        See: withMisfireHandlingInstructionFireAndProceed) C  ]! ^& I1 W" N( L( v2 P3 d
withMisfireHandlingInstructionIgnoreMisfires
5 |- f- g4 \' _# q6 KMISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY( S' R0 k0 H3 l2 C: X& {) |
https://jira.terracotta.org/jira/browse/QTZ-283
2 A+ J5 t$ j2 F/ @  ~! r$ t( n所有被misfire的执行会被立即执行,然后按照正常调度继续执行trigger。$ J2 E1 F9 q: ~9 ], t' C  _
例如:5 }) @3 g  o# [& |6 @& y
9点和10点的执行(misfire的2个)被立即执行,下次执行将在11点被准时执行。6 i3 X* ~) h- i# I1 _
withMisfireHandlingInstructionFireAndProceed
% d) ], @. v. }! j& W! }MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
6 z4 i3 V4 ^# m& F立即执行第一次misfire的操作,并且放弃其他misfire的(类似所有misfire的操作被合并执行了)。然后继续按调度执行。无论misfire多少次trigger的执行,都只会立刻执行1次。
! w& e* z* a' }例如:
5 Y1 U+ B+ _3 W* {/ Q% u9点和10点的被合并执行一次(换句话说,10点需要执行的那次,被pass了)。下次执行将在11点被准时执行。
; p# N1 g  x3 l& `withMisfireHandlingInstructionDoNothing
4 I) ]4 n9 W, ^4 u. j* ]% @MISFIRE_INSTRUCTION_DO_NOTHING/ Y- q9 Y6 j0 ?% |/ A; T
所有被misfire的执行都被忽略掉,调度器会像平时一样等待下次调度。3 J. f9 [! j5 j4 C/ w
例如:
  I& }/ b" x* f( A& P9点和10点的被忽略掉,好像什么都没发生一样。下次执行将在11点被执行。* z; P! s1 F1 ]2 B9 }
         
( `5 ~4 _% p4 W3 bQTZ-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,关注下。)
' i7 j3 v' b" h  R
1 a2 w) d6 u2 X如你所有,根据实际的设定,不同的trigger会有不同的行为。此外,虽然它提供了smart policy(明智的决策),但是真正使用时,还是要取决于业务需求。
' t( X- R/ R) e从本质上看,主要有三种策略:忽略,立即运行然后继续正常执行,忽略misfire的并等待下次执行。( 原文: ignore, run immediately and continue and discard and wait for next. )$ \1 j! [# ?( r! d
它们有不同的应用场景:
# h- U/ t' h2 y当你需要确保每次调度任务都要被执行的时候,即时它意味着多个misfire的trigger会被触发,那么用ignore policies。试想一下,有一个任务,需要每小时,都根据上一小时的订单去生成报表。如果服务被关闭了8个小时,那你可能仍然是尽快得到那些报表的。这种情况下,配置ignore policies,调度器会尽快将那8小时的调度任务运行一遍的。尽管晚了几个小时,但是仍然是被执行了(最终报告到手了。^_^)。3 \" J. W  j6 L' {9 W- \! N. W
当你需要任务被定期执行,并且当出现misfire的情况后立即运行一次的时候,那么使用now* policies。试想一下,一个任务是每分钟清空文件夹 /tmp。如果调度器在20分钟内繁忙,最后终于可以执行这个任务了,那么你肯定不会希望它执行20次的!一次就足够了,但是要尽快执行。而后,再回到正常的执行间隔--1分钟。
* d1 g7 S7 s' _) N( b当你希望任务能在特定时间点运行的时候,使用next* policies不错。比如你需要在每个整点后15分钟抓取股票的价格。它们的变化非常快,然后现在已经整点后20分了,那么不必烦恼。你刚好错过了5分钟,但是现在你已经不在乎(那时候的价格)了。这时,一个时间间隙总好过一个不准确的值。这种情况Quartz只要跳过misfire的操作,等待下次执行就好了。
- J  L4 j! N; T  O
) F% e8 U& ~$ T* p(此文仅为作者观点,我在翻译过程中,其实也有不太明了之处,但是总体来说,还是清晰的,希望大家在以后使用工具时,也更多的关注工具的一切内在功能。)2 }( c8 N8 V; r9 O- ]% K; N

7 V1 c, x4 Q; n
3 M$ h8 h  U! c( |* U: W再次注明,原文地址: http://java.dzone.com/articles/quartz-scheduler-misfire) j8 _$ G) H8 F- g/ |
如转,请尊重原作者,贴上链接。% e' U+ }8 f# B! Y9 }7 a# s; W* X
  @+ G# e$ q3 n7 k* M

科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、科帮网管理员和版主有权不事先通知发贴者而删除本文


JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

相关帖子
    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表