views:

357

answers:

3

Hi all,

I have 4 servers and JVM is installed on them. I wrote a java service that Quartz calls this services every 10 minutes. But in 4 servers, every 10 minutes 4 calls are done. This sitiuation creates race condition. I want only one service on 4 JVM.

How can I do that with Spring Framework?

+3  A: 

Your question isn't very clear, so let me see if I'm understanding you: you have 4 servers, each running Quartz inside a VM, and each server has the same quartz job scheduled to run every 10 minutes, using a cron expression. Every 10 minutes, all 4 servers kick off the same job, creating your race condition as they all try to do the same thing at the same time.

This isn't really a job for Spring. However, Quartz does have clustering ability, where you configure a job to run only a single server in the cluster. It uses a shared database to coordinate which servers run which job, and makes sure they don't all do it together.

The docs have some info on this here, but in the usual opensymphony.com style they're pretty sparse and unhelpful.

skaffman
I understood the question with your explanation skaffman. Awesome. +1 for this.
peakit
+1  A: 

This is actually pretty easy to set up with Quartz. Spring itself cannot help you much here since it is unaware of the other JVMs that are running. Quartz on the other hand has the concept of a clustered scheduler.

Basically you need to set up a single database that all the 4 JVMs can share. This will be used as a scheduler for all 4 instances. When a job is scheduled, it is run by only one of the instances using the clustered scheduler.

Taken from the Quartz website wiki for clustering ( http://www.opensymphony.com/quartz/wikidocs/ConfigJDBCJobStoreClustering.html), this is an example configuration on how to set up the clustered scheduler. You can also set these properties directly from spring if you are configuring your scheduler that way.

#============================================================================
# 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
Chris Dail
Thank you. This will be helpful for me. I will try it.
Firstthumb
A: 

What I do in our web application is for each job to be wrapped in a class that takes out a global lock across your cluster (I use memcached, as I don't really care if the task gets run too often), and only runs the task if it got the lock. It can then release the lock when the task completes (don't forget to do this in a finally).

One advantage of wrapping each job rather than changing the scheduler is that you can have some jobs that run on all the machines, and some that only run on one.

davidsheldon