4 つのサーバーがあり、JVM がインストールされています。Quartz がこのサービスを 10 分ごとに呼び出す Java サービスを作成しました。しかし、4 つのサーバーでは、10 分ごとに 4 つの呼び出しが行われます。この状況により、競合状態が発生します。4 つの JVM で 1 つのサービスのみが必要です。
Spring Framework でそれを行うにはどうすればよいですか?
4 つのサーバーがあり、JVM がインストールされています。Quartz がこのサービスを 10 分ごとに呼び出す Java サービスを作成しました。しかし、4 つのサーバーでは、10 分ごとに 4 つの呼び出しが行われます。この状況により、競合状態が発生します。4 つの JVM で 1 つのサービスのみが必要です。
Spring Framework でそれを行うにはどうすればよいですか?
これは実際、Quartz で設定するのは非常に簡単です。Spring 自体は、実行中の他の JVM を認識していないため、ここではあまり役に立ちません。一方、Quartz にはクラスター化されたスケジューラーの概念があります。
基本的に、4 つの JVM すべてが共有できる単一のデータベースをセットアップする必要があります。これは、4 つのインスタンスすべてのスケジューラとして使用されます。ジョブがスケジュールされると、クラスタ化されたスケジューラを使用してインスタンスの 1 つだけによって実行されます。
クラスタリング用の Quartz Web サイト wiki ( http://www.opensymphony.com/quartz/wikidocs/ConfigJDBCJobStoreClustering.html ) から取得した、これはクラスタ化されたスケジューラをセットアップする方法の構成例です。スケジューラをそのように構成している場合は、Spring からこれらのプロパティを直接設定することもできます。
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.driver = oracle.jdbc.driver.OracleDriver
org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@polarbear:1521:dev
org.quartz.dataSource.myDS.user = quartz
org.quartz.dataSource.myDS.password = quartz
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.dataSource.myDS.validationQuery=select 0 from dual
あなたの質問はあまり明確ではないので、私があなたを理解しているかどうかを確認させてください: 4 つのサーバーがあり、それぞれが VM 内で Quartz を実行しており、各サーバーには、cron 式を使用して 10 分ごとに実行するようにスケジュールされた同じ Quartz ジョブがあります。 . 10 分ごとに 4 つのサーバーすべてが同じジョブを開始し、すべてのサーバーが同時に同じことを実行しようとするため、競合状態が発生します。
これは本当にSpringの仕事ではありません。ただし、Quartz にはクラスタリング機能があり、クラスタ内の単一のサーバーのみを実行するようにジョブを構成します。共有データベースを使用して、どのサーバーがどのジョブを実行するかを調整し、すべてが一緒に実行されないようにします。
ドキュメントにはこれに関する情報がいくつかあります ここ、しかし通常のopensymphony.comスタイルでは、それらはかなりまばらで役に立ちません。
私がWebアプリケーションで行うことは、各ジョブを、クラスター全体でグローバルロックを取得するクラスにラップし(タスクが頻繁に実行されるかどうかは気にしないため、memcachedを使用します)、実行するだけです。ロックを取得した場合のタスク。その後、タスクが完了するとロックを解除できます(でこれを行うことを忘れないでくださいfinally
)。
スケジューラーを変更するのではなく、各ジョブをラップすることの利点の1つは、すべてのマシンで実行されるジョブと、1つだけで実行されるジョブを使用できることです。