cron-ähnlicher wiederkehrender Aufgabenplanerentwurf

8

Angenommen, Sie möchten wiederkehrende Aufgaben planen, beispielsweise:

  • Senden Sie jeden Mittwoch um 10 Uhr eine E-Mail
  • Erstellen Sie eine Zusammenfassung am ersten Tag jedes Monats

Und Sie möchten dies für eine angemessene Anzahl von Benutzern in einer Web-App tun - dh. 100k Benutzer kann jeder Benutzer entscheiden, was wann geplant werden soll.

Und Sie möchten sicherstellen, dass die geplanten Elemente ausgeführt werden, auch wenn sie ursprünglich nicht erkannt wurden - z. Aus irgendeinem Grund wurde die E-Mail am Mittwoch um 10 Uhr nicht gesendet, sie sollte beim nächsten Überprüfungsintervall gesendet werden, sagen wir Mittwoch um 11 Uhr.

Wie würden Sie das gestalten?

Wenn Sie cron verwenden, um Ihre Planungs-App alle x Minuten auszulösen, was ist eine gute Möglichkeit, den Teil zu implementieren, der entscheidet, was zu jedem Zeitpunkt ausgeführt werden sollte?

Die cron-ähnlichen Implementierungen, die ich gesehen habe, vergleichen die aktuelle Zeit mit der Auslösezeit für alle angegebenen Objekte, aber ich möchte auch mit verpassten Objekten umgehen.

Ich habe das Gefühl, dass es einen schlaueren Entwurf gibt als den, den ich gerade koche, also bitte erleuchte mich.

    
Parand 20.10.2010, 17:50
quelle

3 Antworten

6

Es gibt grundsätzlich zwei Designs.

One wird regelmäßig ausgeführt und vergleicht die aktuelle Zeit mit der Zeitplanungsspezifikation (d. h. "Führt das jetzt aus?") und führt diejenigen aus, die sich qualifizieren.

Die andere Methode verwendet die aktuelle Zeitplanspezifikation und findet die NEXT-Zeit, die das Element auslösen soll. Dann vergleicht es die aktuelle Zeit mit all diesen Elementen, deren "nächstes Mal" kleiner ist als "aktuelle Zeit", und feuert diese ab. Wenn ein Artikel fertiggestellt ist, wird er für das neue "nächste Mal" neu geplant.

Die erste Technik kann "verpasste" Objekte nicht behandeln, die zweite Technik kann nur mit den zuvor geplanten Elementen umgehen.

Beachten Sie ausdrücklich, dass Sie einen Zeitplan haben, der einmal pro Stunde zu jeder vollen Stunde ausgeführt wird.

Also, sagen wir, 13.00, 14.00, 15.00, 16.00

Um 13:30 Uhr ist die Ausführungsaufgabe inaktiv und führt keine Prozesse aus. Es beginnt nicht vor 15.20 Uhr.

Bei Verwendung der ersten Technik hat der Scheduler die 1pm-Task ausgelöst, aber nicht die 2pm- und 3pm-Tasks abgefeuert, da sie nach Ablauf dieser Zeit nicht ausgeführt wurde. Der nächste Job, der ausgeführt wird, ist der 16.00 Uhr-Job um 16.00 Uhr.

Unter Verwendung der zweiten Technik hat der Scheduler die 1pm-Aufgabe ausgelöst und die nächste Aufgabe um 14 Uhr geplant. Da das System ausgefallen war, wurde die 2-Uhr-Aufgabe nicht ausgeführt, und auch nicht die 3-Uhr-Aufgabe. Aber als das System um 3:20 Uhr neu gestartet wurde, sah es, dass es die 14-Uhr-Aufgabe "verfehlte" und um 3:20 Uhr abgefeuert und dann wieder für 4 Uhr geplant hatte.

Jede Technik hat ihre Höhen und Tiefen. Mit der ersten Technik vermisst du Jobs. Mit der zweiten Technik können Sie immer noch Jobs verpassen, aber es kann "aufholen" (bis zu einem gewissen Punkt), aber es kann auch einen Job "zur falschen Zeit" laufen lassen (vielleicht sollte es für eine Stunde zu der vollen Stunde laufen) Grund).

Ein Vorteil der zweiten Technik besteht darin, dass Sie sich nicht um ein kaskadierendes Jobproblem kümmern müssen, wenn Sie am Ende des ausgeführten Jobs einen neuen Termin planen.

Bedenken Sie, dass Sie eine Arbeit haben, die jede Minute ausgeführt wird. Bei der ersten Technik wird der Job jede Minute ausgelöst. Wenn der Job jedoch nicht innerhalb der Minute fertiggestellt wird, können Sie normalerweise zwei Jobs ausführen (einen zu spät, den anderen zum Start). Dies kann ein Problem darstellen, wenn der Job nicht gleichzeitig mehr als einmal ausgeführt werden soll. Und es kann sich verschlimmern (wenn es ein echtes Problem gibt, haben Sie nach 10 Minuten 10 Jobs, die sich gegenseitig bekämpfen).

Bei der zweiten Technik, wenn Sie am Ende des Jobs planen, wenn ein Job gerade einmal über eine Minute läuft, "überspringen" Sie eine Minute und starten die nächste Minute, anstatt weiter zu laufen Sie können also für jede Minute einen Job planen, der tatsächlich um 13:01, 13:03, 13:05 usw. läuft.

Abhängig von Ihrem Job-Design kann beides "gut" oder "schlecht" sein. Es gibt keine richtige Antwort hier.

Schließlich ist die Implementierung der ersten Technik wirklich, ziemlich trivial im Vergleich zur Implementierung der zweiten. Der Code, um zu bestimmen, ob eine Cron-Zeichenkette (sagen wir) mit einer gegebenen Zeit übereinstimmt, ist im Vergleich zu dem, zu welchem ​​Zeitpunkt eine Cron-Zeichenkette gültig ist, NEXT. Ich weiß, und ich habe ein paar hundert Zeilen Code, um es zu beweisen. Es ist nicht schön.

    
Will Hartung 20.10.2010, 18:08
quelle
4

Falls Sie das Design überspringen und anfangen möchten, werfen Sie einen Blick auf Sellerie Ссылка . Der Scheduler heißt Selleriebeat.

Bearbeiten: Auch relevant: Wie 100.000 E-Mails wöchentlich gesendet werden?

    
tback 20.10.2010 20:55
quelle
2

Die Verwendung eines Backing-Java-Prozesses mit Quartz-Scheduler ist eine mögliche Lösung. Ich glaube, dass Quarz auf dieses Niveau vernünftig skalieren sollte. Siehe diese verwandte SO Frage: "Wie skaliert man den Quartz Scheduler" .

Wenn Sie sich die Quartz-Dokumentation genau ansehen, werden Sie feststellen, dass Ihre Bedenken hinsichtlich auslösender und fehlgeschlagener Ausführungen sauber behandelt werden und Ihnen eine Reihe geeigneter Richtlinien zur Auswahl bieten. Was die Skalierbarkeit anbelangt, glaube ich, dass Sie Jobs in einem JDBC-Hintergrundspeicher speichern können.

Struck out, da der Fragesteller gezielt nach einer Designdiskussion gesucht hat ... Wenn Sie Ihre anfängliche StackOverflow-Suche vor dem Stellen der Frage in Bezug auf "Task-Scheduler für Python" gerahmt haben, hätten Sie diese Frage gestellt: " Ein Enterprise-Scheduler für Python ... ". Ich empfehle dringend, nach einer bestehenden Implementierung zu suchen, anstatt eine NIH-Entwicklung für so etwas zu versuchen, trotz der großartigen Beobachtungen darüber, wie Sie dies in der anderen Antwort tun könnten. Angesichts Ihrer erklärten Ziele für die Skalierbarkeit ziehen Sie sich eine ziemlich herausfordernde Aufgabe zu und sollten alle anderen Optionen eliminieren, bevor Sie sich von einem völlig neuen Thema zu einem so stark entwickelten Thema verabschieden. Ein möglicher Weg wäre die Anpassung an das vielbeachtete Quartz über Jython und die Entscheidung, ob Ihre Anwendungsfälle in diesem Kontext mit minimalem Eintauchen in die Java-Welt behandelt werden könnten (vermutlich nicht Ihre erste Wahl).

    
andersoj 20.10.2010 17:52
quelle

Tags und Links