Quartz 2.2多调度程序和@DisallowConcurrentExecution

时间:2016-02-09 12:43:17

标签: java quartz-scheduler

请考虑这个例子。

示例Web应用程序在启动时调用scheduler.start()。调度程序配置为将其作业存储在DB中。

将应用程序复制到六个Web服务器上。

因此,如果我们启动六个Web服务器,我们将在一个DB上有六个具有相同名称的调度程序。如https://quartz-scheduler.org/documentation/quartz-2.1.x/cookbook/MultipleSchedulers中所述:

  

永远不要针对同一组数据库表启动(scheduler.start())非群集实例,而任何其他具有相同调度程序名称的实例正在运行(start()ed)。您可能会遇到严重的数据损坏,并且肯定会遇到不稳定的行为。

所以这会失败。

我的问题是,如果我确定我的所有工作都@DisallowConcurrentExecution将会起作用,或者它仍会失败?!

如果@DisallowConcurrentExecution无效,我应该手动将一台服务器配置为Master

public class StartUp implements ServletContextListener {

   public void contextInitialized(ServletContextEvent event) {
       if(THIS_IS_MASTER_TOMCAT){
         scheduler.start()
       }
}

有更好的方法吗?!

1 个答案:

答案 0 :(得分:4)

基本上Rene M.是正确的。以下是与Quartz相关的文档:

http://www.quartz-scheduler.org/documentation/quartz-2.2.x/configuration/ConfigJDBCJobStoreClustering.html

现在我们公司自己使用的一些背景和概念性例子。我们在 Wildfly Cluster中使用石英聚类模式。这就是每个wildfly集群节点运行石英。由于quartz本身在集群模式下运行并且指向相同的数据库模式,因此我们保证每个集群运行一个作业。再次,请参阅文档。关键问题是:

  1. 单个石英簇必须针对单个石英数据库运行 架构。你显然必须创建关系数据库表 文件。没什么大不了的。
  2. 您必须设置quartz.property文件 正确,并且必须存在其中每个节点的副本 簇。 完全相同的quartz.property文件
  3. 最后,您必须使用NonJTA数据源,否则石英群集将失败。这通常意味着在Wildfly世界石英 将需要它自己的     数据源。
  4. quartz.property示例:

        #============================================================================
    # Configure Main Scheduler Properties 
    #============================================================================
    
    org.quartz.scheduler.instanceName = BjondScheduler
    org.quartz.scheduler.instanceId = AUTO
    
    #============================================================================
    # Configure ThreadPool 
    #============================================================================
    
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 5
    
    #============================================================================
    # Configure JobStore 
    #============================================================================
    
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
    org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
    org.quartz.jobStore.useProperties = false
    org.quartz.jobStore.tablePrefix=QRTZ_
    org.quartz.jobStore.isClustered = true
    org.quartz.jobStore.clusterCheckinInterval = 5000
    
    org.quartz.scheduler.wrapJobExecutionInUserTransaction = true
    org.quartz.scheduler.userTransactionURL = java:jboss/UserTransaction
    
    org.quartz.jobStore.dataSource = PostgreSQLDS
    org.quartz.jobStore.nonManagedTXDataSource = PostgreSQLDSNoJTA
    
    org.quartz.dataSource.PostgreSQLDSNoJTA.jndiURL=java:jboss/datasources/PostgreSQLDSNoJTA
    org.quartz.dataSource.PostgreSQLDS.jndiURL=java:jboss/datasources/PostgreSQLDS
    
    
    #============================================================================
    # Configure Logging
    #============================================================================
    #org.quartz.plugin.jobHistory.class=org.quartz.plugins.history.LoggingJobHistoryPlugin
    #org.quartz.plugin.jobHistory.jobToBeFiredMessage=Bjond Job [{1}.{0}] to be fired by trigger [{4}.{3}] at: {2, date, HH:mm:ss MM/dd/yyyy} re-fire count: {7}
    #org.quartz.plugin.jobHistory.jobSuccessMessage=Bjond Job [{1}.{0}] execution complete and reports: {8}
    #org.quartz.plugin.jobHistory.jobFailedMessage=Bjond Job [{1}.{0}] execution failed with exception: {8}
    #org.quartz.plugin.jobHistory.jobWasVetoedMessage=Bjond Job [{1}.{0}] was vetoed. It was to be fired by trigger [{4}.{3}] at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}
    

    现在我们在standalone.xml中的数据源代码段:

                <datasource jta="false" jndi-name="java:jboss/datasources/PostgreSQLDSNoJTA" pool-name="PostgreSQLDSNoJTA" enabled="true" use-java-context="true" use-ccm="true">
    

    根据您的要求填写此数据源元素的其余部分。 @DisallowConcurrentExecution是一个好主意,可以防止单个节点上的多个作业执行特定方法,但是石英集群会阻止在多个VM上运行相同的作业;不是这个注释。