Kann ich warten, dass Quartz Jobs in der Reihenfolge ausgelöst werden, in der sie ausgelöst wurden?

9

Ich habe eine Anwendung, die den Quartz Scheduler verwendet, um Jobs zu planen. Die Anwendung läuft derzeit Quartz Version 1.6.2. Mein JobStore ist org.quartz.impl.jdbcjobstore.JobStoreTX mit einer Oracle-Datenbank, die dies unterstützt. Clustering ist aktiviert, aber es gibt nur einen Scheduler, der die Datenbank verwendet. Mein Quartz threadPool ist wie folgt konfiguriert:

%Vor%

Meine Jobs laufen schon lange, daher ist es ziemlich üblich, dass fünf Jobs ausgeführt werden (die von meinem thead-Pool maximal zulässige Anzahl), wenn Trigger neue Jobs auslösen. Die neu ausgelösten Jobs führen zu Fehlzündungen und ich sehe Logmeldungen wie die folgenden:

%Vor%

Sobald ein laufender Job abgeschlossen ist, wird einer der fehlgeschlagenen Jobs abgeholt und normal ausgeführt. Quartz scheint jedoch zufällig einen fehlgesteuerten Auftrag aufzunehmen, ohne die Reihenfolge zu berücksichtigen, in der die Aufträge ursprünglich ausgeführt wurden. Im Idealfall möchte ich, dass sie in der Reihenfolge, in der sie ausgeführt werden sollten, aufgrund ihrer ursprünglichen Feuerzeiten aufgenommen werden.

Ist es möglich, dass meine wartenden (fehlgesteuerten) Jobs in der Reihenfolge ausgelöst werden, in der sie ausgelöst wurden, sobald Speicherplatz im Quartz ThreadPool verfügbar wird?

    
Jon Quarfoth 23.07.2010, 17:51
quelle

4 Antworten

2

Wenn Quarz einen Auslöser behandelt, der seine Feuerzeit verpasst hat, wird der nextFireTime des Auslösers aktualisiert. Standardmäßig wird ein Trigger als verpasst betrachtet, wenn nextFireTime in der Vergangenheit länger als 60 Sekunden ist. Verpasste Trigger sollten immer noch basierend auf nextFireTime und Prioritätsreihenfolge ausgewählt werden, aber ich vermute, dass es zufällig erscheint, da einige Trigger aktualisiert wurden und andere nicht.

Ich würde vorschlagen, die Eigenschaft org.quartz.jobStore.misfireThreshold zu erhöhen. Siehe Ссылка (obwohl die Eigenschaft für alle JobStores identisch ist). Dies sollte es weniger wahrscheinlich machen, dass Ihre Trigger neu geplant werden.

    
samblake 21.04.2016, 16:01
quelle
2

Ich höre, dass Sie in ein Fehlzündungsszenario geraten (ein Szenario, in dem mehr Jobs zur Ausführung bereitstehen als Worker-Threads). Legen Sie die Fehlzündungsanweisung und / oder die Prioritätseigenschaft für die Trigger fest, um zu ändern, wie sich jedes verhält, nachdem es seine Feuerzeit überschritten hat.

Sie könnten auch erwägen, den Fehlzündungsschwellenwert zu erhöhen, wodurch sich die Zeit ändern würde, die ein Trigger "spät" auf die Ausführung eines Threads wartet, bevor er als Fehlzündung betrachtet wird (und seine Fehlzündungsanweisung angewendet wird). .

  

Ist es möglich, dass meine wartenden (fehlgesteuerten) Jobs in der Reihenfolge ausgelöst werden, in der sie ausgelöst wurden, sobald Speicherplatz im Quartz ThreadPool verfügbar wird?

Die "nichts tun" -Anweisungen lassen das Feuer so wie es ist.

    
jhouse 11.04.2011 13:44
quelle
0

Wenn Sie sich den Quarz Thread-Pool ansehen, wird eine Wartezeit benötigt () / notify () Schleife, die nicht fair ist, und wird zufällig einen neuen Thread auswählen, wenn mehrere Threads warten.

Sie könnten Ihre eigene Instanz von ThreadPool verwenden, die fair ist. Kopieren Sie den Code aus SimpleThreadPool, aber ersetzen Sie das Locking um nextRunnableLock durch java.util.ReentrantLock und übergeben Sie den Fair-Konstruktor. Verwenden Sie in Ihrem modifizierten SimpleThreadPool ReentrantLock.lock () / unlock () statt synchronisiert und verwenden Sie ReentrantLock.newCondition (). Signal () / await () anstelle von wait / notify und es könnte Ihr Problem lösen.

>     
sbridges 10.04.2011 06:14
quelle
0

Im Fall von CronTrigger kann die Methode updateAfterMisfire() die Aufgabe um new Date() case MISFIRE_INSTRUCTION_FIRE_ONCE_NOW policy neu planen.

Wenn mehrere Tasks fehlgeschlagen sind, können mehrere gleichzeitig verschoben werden (gleiche Millisekunde), da der Computer schnell läuft.

Als eine Konsequenz, und wenn keine Priorität definiert ist, wird der Scheduler die erste nächste Aufgabe übernehmen, alle mit demselben NextFireTime , entsprechend dem Schlüssel- oder vollständigen Namen.

Die Methode

updateAfterMisfire() sollte die Aufgabe als Beispiel auf eine eindeutige date umstellen, die ein Thread.sleep(25) verwendet.

    
Vincent 11.05.2015 15:57
quelle

Tags und Links