2015-05-20 7 views
8

ich einen Windows-Dienst, der den Aufbau einer geplanten Aufgabe ausführt, die eine Warteschlange von Befehlen verarbeitet (von einem Legacy-System) in einem regelmäßigen Intervall (einmal pro min) unter Verwendung Quartz.netQuartz.net Erste Aussetzer zu ignorieren

Wenn die Aufgabe länger als 1 Minute dauert, was ungewöhnlich wäre, aber unter bestimmten Umständen möglich wäre, würde ich gerne die Auslöser ignorieren, die sie nicht ausgelöst haben.

Allerdings kann ich nicht scheinen, dass dies geschieht. Es führt die Verarbeitung durch und zündet dann schnell alle ausgelösten Auslöser in schneller Folge. Wie ich verstehe, können Sie einen Schwellenwert für die Fehlzündungen festlegen, aber ich bin nicht in der Lage, dies zum Funktionieren zu bringen.

Ich verwende [DisallowConcurrentExecution()] für den Job, um sicherzustellen, dass nur eine Instanz des Jobs gleichzeitig ausgeführt wird.

Unten sind ein paar Schnipsel. Zuerst einige Config-Informationen übergeben - setzt man so die Fehlzündungsschwelle?

NameValueCollection config = new NameValueCollection(); 
    config.Add("quartz.jobStore.misfireThreshold", "600000"); 

    schedFact = new StdSchedulerFactory(config); 

Aufbau eines Triggers mit dem, was ich nehme an, die richtige Einstellung von Ignore Aussetzern sein:

var trigger = TriggerBuilder.Create() 
        .WithIdentity("trigger1", "group1") 
        .StartNow() 
        .WithSimpleSchedule( x => x.WithMisfireHandlingInstructionIgnoreMisfires() 
        .WithIntervalInSeconds(60) 
        .RepeatForever()) 
        .Build(); 

Gedanken sehr geschätzt.

Code für den Job: Nur zu diesem Zeitpunkt mit groben Ideen zu spielen, so nur in einer Konsole App laufen und einen Auftrag zufällig verzögert, so dass es über das Intervall schießt, die nur auf 10 Sekunden dafür eingestellt ist. Alle gesicherten Fehlzündungen werden nach ein paar Verzögerungen schnell nacheinander ausgelöst.

[DisallowConcurrentExecution()] 
public class SomeJob : IJob 
{ 
    public SomeJob() { } 
    public void Execute(IJobExecutionContext context) 
    { 
     Random rnd = new Random(DateTime.UtcNow.Second); 
     int delay = rnd.Next(2); 
     Console.WriteLine("Executing Job with delay of "+ delay + " at " + DateTime.UtcNow.ToString()); 

     if (delay == 1) 
     { 
      System.Threading.Thread.Sleep(1000 * 25); // sleep for 25 seconds 
     } 
    } 
} 





Example console output: 
Executing Job with delay of 1 at 21/05/2015 21:27:17 
Executing Job with delay of 1 at 21/05/2015 21:27:42 
Executing Job with delay of 0 at 21/05/2015 21:28:07 <-- stacked misfires 
Executing Job with delay of 0 at 21/05/2015 21:28:07 <-- 
Executing Job with delay of 0 at 21/05/2015 21:28:07 <-- 
Executing Job with delay of 0 at 21/05/2015 21:28:07 <-- 
Executing Job with delay of 0 at 21/05/2015 21:28:16 
Executing Job with delay of 0 at 21/05/2015 21:28:26 
Executing Job with delay of 1 at 21/05/2015 21:28:36 
Executing Job with delay of 0 at 21/05/2015 21:29:01 
Executing Job with delay of 0 at 21/05/2015 21:29:01 
Executing Job with delay of 1 at 21/05/2015 21:29:06 
+0

Können Sie den Code für Ihren Job einfügen? – LeftyX

+0

Danke für die Suche - Ich habe den ursprünglichen Beitrag mit Code aus dem Job aktualisiert. –

+0

Alberne Frage: Wie kann Ihr Job alle 30 Sekunden ausgelöst werden, wenn Ihr Auslöser jede Minute ausgelöst wird? – LeftyX

Antwort

13

WithMisfireHandlingInstructionIgnoreMisfires() ist die falsche Methode für das, was Sie wollen, ist es nicht die Aufgabe auslösen wird nicht Aussetzern bedeutet, es bedeutet, dass es alle Trigger ausgelöst, die so schnell wie möglich verpasst wurden, und wird dann zu normalen zurückgehen Zeitplan. Was du siehst, geschieht.

Was Sie brauchen, ist WithMisfireHandlingInstructionNextWithRemainingCount(). Dies signalisiert dem Scheduler, Fehlzündungen zu ignorieren und auf die nächste geplante Zeit zu warten. Fehlzündungsstrategien können ein wenig verwirrend sein, für eine kurze Erklärung aussehen here (es ist für den Java-Scheduler, aber es spielt keine Rolle).

Auch mit der richtigen Strategie müssen Sie verstehen, wie die Fehlzündungsschwelle funktioniert - wenn Sie einen Fehler bekommen, kann Ihr fehlgeschlagener Trigger trotzdem ausgelöst werden.

Aus der Dokumentation: "Eine Fehlzündung ist die Zeitspanne, in der ein Trigger seine nächste Feuerzeit verpasst haben muss, damit er als" fehlgezündet "gilt und seine Fehlzündungsanweisung angewendet wird".

Sie den Wert auf 600000 Millisekunden festgelegt haben (und dieser Wert für alle Trigger ist leider keinen Schwellenwert gibt pro Trigger) - die Strategie Fehlzündung nur nach die Zeit, wenn Ihr Trigger ausgelöst 600000 Millisekunden angewendet werden es hätte gefeuert werden sollen. Sie können es nach Ihren Anforderungen senken oder erhöhen.

Weitere Informationen zur Fehlzündungsschwelle finden Sie unter here.

+0

Brilliant danke, guter Link. Die Umstellung auf WithMisfireHandlingInstructionNextWithRemainingCount und die Einstellung der Fehlzündungsschwelle auf die Hälfte des Intervalls scheint den Job großartig zu machen. –

+0

@AbsolutelyN froh, dass es funktioniert, denken Sie daran, auch zu verbessern –

+0

Wird tun, sobald ich über 15 Ruf ... –