Ich schreibe eine Anwendung mit einem Cron-Job, der alle 60 Sekunden ausgeführt wird. Die Anwendung ist so konfiguriert, dass sie bei Bedarf auf mehrere Instanzen skaliert werden kann. Ich möchte die Aufgabe nur auf einer Instanz alle 60 Sekunden ausführen (auf einem beliebigen Knoten). Ich kann keine Lösung für dieses Problem finden und bin überrascht, dass es zuvor nicht mehrmals gefragt wurde. Ich benutze Spring 4.1.6.
<task:scheduled-tasks>
<task:scheduled ref="beanName" method="execute" cron="0/60 * * * * *"/>
</task:scheduled-tasks>
spring
spring-scheduled
user3131879
quelle
quelle
CronJob
inkubernetes
?Antworten:
Es gibt ein ShedLock- Projekt, das genau diesem Zweck dient. Sie kommentieren nur Aufgaben, die bei der Ausführung gesperrt werden sollen
Konfigurieren Sie Spring und einen LockProvider
quelle
Ich denke, Sie müssen Quartz Clustering mit JDBC-JobStore für diesen Zweck verwenden
quelle
Dies ist eine weitere einfache und robuste Methode, um einen Job in einem Cluster sicher auszuführen. Sie können basierend auf der Datenbank die Aufgabe nur ausführen, wenn der Knoten der "Leiter" im Cluster ist.
Auch wenn ein Knoten ausfällt oder im Cluster heruntergefahren wird, wird ein anderer Knoten zum Leader.
Alles, was Sie haben, ist, einen "Führerwahl" -Mechanismus zu erstellen und jedes Mal zu überprüfen, ob Sie der Führer sind:
Befolgen Sie diese Schritte:
1. Definieren Sie das Objekt und die Tabelle, die einen Eintrag pro Knoten im Cluster enthalten:
}}
2.Erstellen Sie den Dienst, der a) den Knoten in die Datenbank einfügt, b) nach Leader sucht
}}
3.Ping der Datenbank, um zu senden, dass Sie am Leben sind
4.Sie sind bereit! Überprüfen Sie einfach, ob Sie der Anführer sind, bevor Sie die Aufgabe ausführen:
quelle
Stapel- und geplante Jobs werden normalerweise auf ihren eigenen Standalone-Servern ausgeführt, weg von kundenorientierten Apps. Daher ist es nicht üblich, einen Job in eine Anwendung aufzunehmen, die voraussichtlich in einem Cluster ausgeführt wird. Darüber hinaus müssen sich Jobs in Clusterumgebungen normalerweise nicht um andere Instanzen desselben Jobs kümmern, die parallel ausgeführt werden. Dies ist ein weiterer Grund, warum die Isolierung von Jobinstanzen keine große Anforderung ist.
Eine einfache Lösung wäre, Ihre Jobs in einem Spring-Profil zu konfigurieren. Zum Beispiel, wenn Ihre aktuelle Konfiguration lautet:
ändere es in:
Starten Sie dann Ihre Anwendung auf nur einem Computer mit
scheduled
aktiviertem Profil (-Dspring.profiles.active=scheduled
).Wenn der Primärserver aus irgendeinem Grund nicht mehr verfügbar ist, starten Sie einfach einen anderen Server mit aktiviertem Profil, und die Dinge funktionieren weiterhin einwandfrei.
Die Dinge ändern sich, wenn Sie auch für die Jobs ein automatisches Failover wünschen. Anschließend müssen Sie den Job auf allen Servern ausführen und die Synchronisierung über eine gemeinsame Ressource wie eine Datenbanktabelle, einen Cluster-Cache, eine JMX-Variable usw. überprüfen.
quelle
get
undset
Operation verwenden, um dies zu erreichen.dlock ist so konzipiert, dass Aufgaben nur einmal ausgeführt werden, indem Datenbankindizes und -einschränkungen verwendet werden. Sie können einfach so etwas wie unten tun.
Lesen Sie den Artikel über die Verwendung.
quelle
Ich verwende eine Datenbanktabelle, um das Sperren durchzuführen. Es kann jeweils nur eine Aufgabe in die Tabelle eingefügt werden. Der andere erhält eine DuplicateKeyException. Die Einfüge- und Löschlogik wird durch einen Aspekt um die Annotation @Scheduled behandelt. Ich benutze Spring Boot 2.0
quelle
Sie können dazu einen einbettbaren Scheduler wie db-scheduler verwenden . Es verfügt über dauerhafte Ausführungen und verwendet einen einfachen optimistischen Sperrmechanismus, um die Ausführung durch einen einzelnen Knoten zu gewährleisten.
Beispielcode, wie der Anwendungsfall erreicht werden kann:
quelle
Der Spring-Kontext ist nicht geclustert, daher ist die Verwaltung der Aufgabe in verteilten Anwendungen etwas schwierig. Sie müssen Systeme verwenden, die jgroup unterstützen, um den Status zu synchronisieren und Ihre Aufgabe die Priorität zum Ausführen der Aktion übernehmen zu lassen. Oder könnten Sie ejb Kontext verwenden Cluster - Verwaltung ha Singleton Service wie Jboss ha Umgebung https://developers.redhat.com/quickstarts/eap/cluster-ha-singleton/?referrer=jbd Oder könnten Sie gruppierten Cache und Zugriffssperre Ressource verwenden Zwischen dem Dienst und dem ersten Dienst wird die Sperre die Aktion bilden oder eine eigene jgroup implementieren, um Ihren Dienst zu kommunizieren und die Aktion an einem Knoten auszuführen
quelle