6

我有 4 台服务器,上面安装了 JVM。我写了一个 java 服务,Quartz 每 10 分钟调用一次这个服务。但在 4 台服务器中,每 10 分钟完成 4 次调用。这种情况造成了竞争条件。我只想要 4 个 JVM 上的一项服务。

如何使用 Spring Framework 做到这一点?

4

3 回答 3

3

你的问题不是很清楚,所以让我看看我是否理解你:你有 4 台服务器,每台服务器在 VM 中运行 Quartz,每台服务器都有相同的石英作业,计划每 10 分钟运行一次,使用 cron 表达式. 每 10 分钟,所有 4 台服务器都会启动相同的工作,从而创建您的竞争条件,因为它们都试图同时做同样的事情。

这真的不是 Spring 的工作。但是,Quartz 确实具有集群功能,您可以将作业配置为仅在集群中运行单个服务器。它使用共享数据库来协调哪些服务器运行哪些作业,并确保它们不会一起执行。

文档在这里有一些关于此的信息,但在通常的 opensymphony.com 风格中,它们非常稀疏且无用。

于 2009-07-24T14:08:17.413 回答
3

这实际上很容易用 Quartz 设置。Spring 本身在这里无法为您提供太多帮助,因为它不知道正在运行的其他 JVM。另一方面,Quartz 具有集群调度器的概念。

基本上,您需要设置一个所有 4 个 JVM 都可以共享的数据库。这将用作所有 4 个实例的调度程序。调度作业时,它仅由使用集群调度程序的一个实例运行。

取自 Quartz 网站 wiki for clustering ( 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
于 2009-07-24T14:18:02.767 回答
0

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.

于 2009-11-04T14:13:33.453 回答