【问题标题】:Spring Framework Connecting JVM with each otherSpring框架将JVM相互连接
【发布时间】:2009-07-24 14:02:53
【问题描述】:

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

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

【问题讨论】:

    标签: java spring quartz-scheduler cluster-computing


    【解决方案1】:

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

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

    取自 Quartz 网站 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
    

    【讨论】:

    • 谢谢。这对我会有帮助。我会试试的。
    【解决方案2】:

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

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

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

    【讨论】:

    • 我理解了你的解释 skaffman 的问题。惊人的。为此 +1。
    【解决方案3】:

    我在我们的 Web 应用程序中所做的是将每个作业包装在一个类中,该类在整个集群中取出一个全局锁(我使用 memcached,因为我并不关心任务是否过于频繁地运行),并且只有在获得锁时才运行任务。然后它可以在任务完成时释放锁(不要忘记在finally 中执行此操作)。

    包装每个作业而不是更改调度程序的一个优点是,您可以让一些作业在所有机器上运行,而另一些只在一台机器上运行。

    【讨论】:

      猜你喜欢
      • 2017-01-13
      • 2017-05-22
      • 2016-06-17
      • 2018-10-22
      • 2013-11-22
      • 2017-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多