第七節:Trigger(SimpleTrigger、CronTrigger)啞火(MisFire)策略 :


一. 簡介

1. 什么是啞火

  由於某些原因導致觸發器(trigger)在該觸發的時候沒有得到觸發,后續對應的解決策略即為啞火策略。(個人理解)

2. 啞火觸發的條件

  ①:所有的工作線程都在忙碌,導致某些trigger得不到觸發.(如:simplethreadpool 默認是10個工作線程,但我有15個trigger同時觸發, 恰巧這10個trigger關聯的job耗時都很長,剩下的5個trigger超過了等待時間仍然沒有得到觸發)

  ②:調度器(sheduler)中途掛了,某個時間又恢復了

  ③:設置的trigger的開始時間早於當前時間

 如果沒有觸發啞火的條件,則不會觸發啞火策略,之前的全部都是按照忽略來計算的,后續按照正常規律來進行。如果不設置開始時間,即為當前時間開始,不觸發啞火策略。

 下面介紹兩類Trigger對應的啞火策略:SimpleTrigger和CronTrigger (前提:案例設置時間早於當前時間的,即都是有錯過的)

 

二. SimpleTrigger啞火策略詳解

   這里要分三種情況來討論,執行指定次數的情況WithRepeatCount(n),n=1、n>1、n=forever三種情況,重點理解n>1的情況,另外兩種都是他的特殊情況而已。

(一):執行指定次數的情況(WithRepeatCount(n) n>1) 只要記住這種情況,下面的B和C都能分析出來

(1).默認 :立即執行,修改當前調度時間,總數保持不變 (等價於WithMisfireHandlingInstructionNowWithExistingCount)

  詳見下面解析

(2).WithMisfireHandlingInstructionIgnoreMisfires:錯過的立即追趕,然后正常調度。

  PS:設置的時間早於當前時間,執行的時候,會將當前時間之前錯過的次數一次性執行完,然后正常按照設置的開始時間及規律進行執行。 如果設置的RepeatCount(n)中n的次數小於錯過的次數,只能執行n次,執行完后,將不會在執行了,因為執行次數已經用完了。

  案例:設置的開始時間為8:00,每隔半小時執行一次,執行總次數為5次,當前時間為9:05,那么開始時候會先執行3次,將錯過的一次性執行了,然后按照正常調度執行,下一次執行的時間為9:30,還能執行兩次。

(3).WithMisfireHandlingInstructionNextWithExistingCount:錯過的不管了,按計划等待下次調度,總數不變,結束時間推遲。
  PS:錯過的次數不處理,仍按照設置的規律來執行,執行次數不變,要執行完的RepeatCount(n)中的n.

  案例:設置的開始時間為8:00,每隔半小時執行一次,執行總次數為5次,當前時間為9:05,那么開始時候並沒有調度執行,第一次執行調度的時間為9:30,然后按照正常調度執行,總共執行5次,最后一次時間為11:30。

(4).WithMisfireHandlingInstructionNextWithRemainingCount:錯過的不管了,按計划等待下次調度,但總數要減去misfire錯過的次數
  PS:錯過的次數不處理,仍按照設置的規律來執行,執行總數要 減去 錯過的次數!

    案例:設置的開始時間為8:00,每隔半小時執行一次,執行總次數為5次,當前時間為9:05,那么開始時候並沒有調度執行,第一次執行調度的時間為9:30,然后按照正常調度執行,總共執行      5-3=2 次,最后一次時間為10:00。

(5).WithMisfireHandlingInstructionNowWithExistingCount: 立即執行,修改當前調度時間,總數保持不變
  PS:立即執行,修改當前調度時間的含義為,即使我設置的開始時間早於當前時間,但該啞火策略會立馬執行該觸發器,即運行后,馬上執行了一次,后續的時間間隔均是是以當前執行時間為基礎來進行的,言外之意,之前設置的開始時間沒用了,執行總數不變。

   案例:設置的開始時間為8:00,每隔半小時執行一次,執行總次數為5次,當前時間為9:05,那么開始時候立即執行,第一次執行調度的時間為9:05,然后以9:05為基礎,按照正常調度規律執行,總共執行5次,第二次時間為9:35,最后一次執行時間為11:05。

(6).WithMisfireHandlingInstructionNowWithRemainingCount: 立即執行,修改當前調度時間,總數要減去misfire錯過的次數
  PS:立即執行,修改當前調度時間的含義為,即使我設置的開始時間早於當前時間,但該啞火策略會立馬執行該觸發器,即運行后,馬上執行了一次,后續的時間間隔均是是以當前執行時間為基礎來進行的,言外之意,之前設置的開始時間沒用了。執行總數要 減去 錯過的次數!

  案例:設置的開始時間為8:00,每隔半小時執行一次,執行總次數為5次,當前時間為9:05,那么開始時候立即執行,第一次執行調度的時間為9:05,然后以9:05為基礎,按照正常調度規律執行,總共執行 5-3=2 次,第二次(即最后一次)時間為9:35。

B:只執行一次的情況 (WithRepeatCount(n) n=1) 對A情況的一個特殊分析

(1). 默認:(等價於WithMisfireHandlingInstructionFireNow)

(2). WithMisfireHandlingInstructionFireNow:立即執行

  PS:設置的時間早於當前時間,執行的時候,立即把這一次執行完,后續將不再執行;但設置的時間晚於當前時間,則按照正常規律進行執行了

(3).WithMisfireHandlingInstructionNextWithRemainingCount 和 WithMisfireHandlingInstructionNowWithRemainingCount :不執行了

  PS:設置的時間早於當前時間,執行的時候按照原規律執行,但是次數要減去錯過的次數,這里總共就執行一次,所以就不執行了

 

C:永久執行的情況(RepeatForever) 對A情況的一個特殊分析

(1). 默認:等價與下面的(2),按計划的正常調度執行,執行次數永久執行

(2). WithMisfireHandlingInstructionNextWithExistingCount 和 WithMisfireHandlingInstructionNextWithRemainingCount:按計划的正常調度執行,執行次數永久執行

(3). WithMisfireHandlingInstructionNowWithExistingCount 和 WithMisfireHandlingInstructionNowWithRemainingCount: 立即執行,執行的開始時間改為當前時間,執行次數永久執行

代碼分享:自行替換即可

 1         public static void misfireShow()
 2         {
 3             //1.創建Schedule
 4             IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
 5             //2.創建job (具體的job需要單獨在一個文件中執行)
 6             var job = JobBuilder.Create<HelloJob4>().Build();
 7             //3.配置trigger 
 8             //下面的四個觸發器對應了上面四種情況的測試,時間需要根據實際情況進行配置測試來設置
 9             var trigger1 = TriggerBuilder.Create().StartAt(DateBuilder.DateOf(20, 0, 0))
10                          .WithSimpleSchedule(x => x.WithIntervalInMinutes(30)
11                                                    .WithRepeatCount(8)
12                                                   .WithMisfireHandlingInstructionNowWithExistingCount()
13                                              ).Build();
14             var trigger2 = TriggerBuilder.Create().StartAt(DateBuilder.DateOf(18, 0, 0))
15                              .WithSimpleSchedule(x => x.WithIntervalInSeconds(1)
16                                                        .WithRepeatCount(1)
17                                                       .WithMisfireHandlingInstructionFireNow()
18                                                  ).Build();
19             var trigger3 = TriggerBuilder.Create()
20                                         .StartAt(DateBuilder.DateOf(15, 0, 0, 5, 3, 2018))
21                                         .WithSimpleSchedule(x => x.WithIntervalInMinutes(1)
22                                                                  .WithMisfireHandlingInstructionNowWithRemainingCount()
23                                                                  .RepeatForever()).Build();
24             var trigger4 = TriggerBuilder.Create()
25                                       .StartAt(DateBuilder.DateOf(14, 0, 0))
26                                       .WithCronSchedule("0 0-59 9-23 ? * MON-FRI",x=>x.WithMisfireHandlingInstructionIgnoreMisfires()).Build();
27 
28             //4.開始調度
29             scheduler.ScheduleJob(job, trigger1);
30             scheduler.Start();
31         }

 

三. CronTrigger啞火策略詳解

(1). 默認:錯過的合並,於當前時間執行一次,不修改調度時間,按計划等待下一次調度(等價於下面的 WithMisfireHandlingInstructionFireAndProceed)

(2). WithMisfireHandlingInstructionIgnoreMisfires:錯過的立即追趕,然后正常調度

  ps:錯過多少次,初次執行的時候追趕多少次,追趕的次數的時間是按原規律執行的時間,然后按照原規律進行正常后續調度

(3). WithMisfireHandlingInstructionFireAndProceed:錯過的合並,於當前時間執行一次,不修改調度時間,按計划等待下一次調度

  PS:無論錯過多少次,均在初次運行的時候,即當前時間執行一次,后續的執行仍按照原規律進行執行。

(4). WithMisfireHandlingInstructionDoNothing:錯過的不管了,后續按照正常調度進行

  PS:無論錯過多少次,均忽略,后續的執行仍按照原規律進行執行。

 代碼詳見上面的代碼分享

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM