【问题标题】:Quartz Job executed multiple times simultaneously by each cluster machine, rather than one time by one machine for the entire clusterQuartz Job 由每台集群机器同时执行多次,而不是由一台机器对整个集群执行一次
【发布时间】:2015-01-29 20:51:10
【问题描述】:

目标: * 让 Job1 每 10 分钟为三节点集群运行一次,Job2 每 5 分钟为同一个集群运行一次。每个作业都会生成一封电子邮件;所以在上午 10:55 我应该只收到一封来自集群的 Job2 电子邮件,在上午 11:00 我应该收到一封来自集群的 Job1 电子邮件和一封 Job2 电子邮件,在上午 11:05 我应该只收到一封来自集群的 Job2 电子邮件,等等……

问题: * Job1 在集群中的每个节点上每 10 分钟运行多次,Job2 也是如此(每 5 分钟运行一次除外)。这会导致很多、很多不止一两封电子邮件。

配置: * 三节点linux集群 * 每台机器的 NTP 配置和时间同步 * 甲骨文数据库 * Quartz v2.2.0(集群模式) * 通过 CronTrigger 配置的作业 * 每个节点都有一个相同的独立 Java 应用程序的实例在其上运行,Java 应用程序以集群模式实例化石英调度程序的一个实例。 * 每台机器上的quartz.properties 文件都是相同的。

我已经调查了所有明显的潜在原因,但没有任何解释或解决方法。我什至尝试在作业中插入一个人工的 10 秒睡眠指令,以确保它不会在一秒钟内完成。请在下面找到相关工件(quartz.properties 和日志输出)。任何帮助将不胜感激!

工件 #1:

============================================================================
============================================================================
Q U A R T Z   ---   P R O P E R T I E S 
==================

    #============================================================================
    # Configure Main Scheduler Properties  
    #============================================================================

    org.quartz.scheduler.instanceName: MyQrtzScheduler
    org.quartz.scheduler.instanceId: AUTO

    org.quartz.scheduler.skipUpdateCheck: true

    #============================================================================
    # Configure ThreadPool  
    #============================================================================

    org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount: 1
    org.quartz.threadPool.threadPriority: 5

    #============================================================================
    # Configure JobStore  
    #============================================================================

    org.quartz.jobStore.misfireThreshold: 2592000000

    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=60000

    #============================================================================
    # Other Example Delegates
    #============================================================================
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
    #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate

    #============================================================================
    # Configure Datasources  
    #============================================================================

    org.quartz.dataSource.myDS.driver: oracle.jdbc.driver.OracleDriver
    org.quartz.dataSource.myDS.URL: jdbc:oracle:thin:@myServer:myPort:blah
    org.quartz.dataSource.myDS.user: myDBUser
    org.quartz.dataSource.myDS.password: myDBPassword
    org.quartz.dataSource.myDS.maxConnections: 2
    org.quartz.dataSource.myDS.validationQuery: select 0

    #============================================================================
    # Configure Plugins 
    #============================================================================

    org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin
    org.quartz.plugin.shutdownHook.cleanShutdown: true
    org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin
    org.quartz.plugin.jobHistory.class=org.quartz.plugins.history.LoggingJobHistoryPlugin

工件 #2:

============================================================================
============================================================================
L O G  ---  O U T P U T
==================
    2015-01-29 12:56:16,602 [main]  INFO com.mycompany.myapp.jobs.QuartzHelper - Initializing Quartz scheduler...
    2015-01-29 12:56:16,829 [main]  INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
    2015-01-29 12:56:16,855 [main]  INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
    2015-01-29 12:56:16,855 [main]  INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.2.0 created.
    2015-01-29 12:56:16,857 [main]  INFO org.quartz.plugins.management.ShutdownHookPlugin - Registering Quartz shutdown hook.
    2015-01-29 12:56:16,859 [main]  INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Using db table-based data access locking (synchronization).
    2015-01-29 12:56:16,864 [main]  INFO org.quartz.impl.jdbcjobstore.JobStoreTX - JobStoreTX initialized.
    2015-01-29 12:56:16,865 [main]  INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.0) 'MyQrtzScheduler' with instanceId 'node1_1422554176832'
      Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
      NOT STARTED.
      Currently in standby mode.
      Number of jobs executed: 0
      Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 1 threads.
      Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is clustered.

    2015-01-29 12:56:16,865 [main]  INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'MyQrtzScheduler' initialized from specified file: '/my/install/directory/quartz.properties'
    2015-01-29 12:56:16,866 [main]  INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.2.0
    2015-01-29 12:56:16,866 [main]  INFO com.mycompany.myapp.jobs.QuartzHelper - Quartz scheduler initialized successfully.

    2015-01-29 12:59:53,450 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
    2015-01-29 13:00:00,007 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' is desired by: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:00:00,008 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' is being obtained: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:00:00,809 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' given to: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:00:00,836 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' returned by: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:00:00,839 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'node2_1422546730757.Job1', class=com.mycompany.myapp.job.Job1
    2015-01-29 13:00:00,851 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingTriggerHistoryPlugin - Trigger node2_1422546730757.Job1Trigger fired job node2_1422546730757.Job1 at:  13:00:00 01/29/2015
    2015-01-29 13:00:00,852 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingJobHistoryPlugin - Job node2_1422546730757.Job1 fired (by trigger node2_1422546730757.Job1Trigger) at:  13:00:00 01/29/2015
    2015-01-29 13:00:00,852 [MyQrtzScheduler_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job node2_1422546730757.Job1
    2015-01-29 13:00:00,853 [MyQrtzScheduler_Worker-1]  INFO com.mycompany.myapp.job.Job1 - ***Executing Inbound File SLA Job...
    2015-01-29 13:00:02,054 [MyQrtzScheduler_Worker-1]  INFO com.mycompany.myapp.job.Job1 - ***Inbound File SLA Job: No SLA breaches found...
    2015-01-29 13:00:02,150 [MyQrtzScheduler_Worker-1]  INFO com.mycompany.myapp.job.Job1 - Job1 completed successfully in [1297ms]; sleeping [63703ms] to meet the required minimum runtime for quartz-jobs
    2015-01-29 13:00:24,881 [QuartzScheduler_MyQrtzScheduler-node1_1422554176832_ClusterManager] DEBUG org.quartz.impl.jdbcjobstore.JobStoreTX - ClusterManager: Check-in complete.
    2015-01-29 13:01:05,862 [MyQrtzScheduler_Worker-1]  INFO com.mycompany.myapp.job.Job1 - Job1 sleep-delay completed.
    2015-01-29 13:01:05,864 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingJobHistoryPlugin - Job node2_1422546730757.Job1 execution complete at  13:01:05 01/29/2015 and reports: SUCCESS
    2015-01-29 13:01:05,865 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingTriggerHistoryPlugin - Trigger node2_1422546730757.Job1Trigger completed firing job node2_1422546730757.Job1 at  13:01:05 01/29/2015 with resulting trigger instruction code: DO NOTHING
    2015-01-29 13:01:05,868 [MyQrtzScheduler_Worker-1] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' is desired by: MyQrtzScheduler_Worker-1
    2015-01-29 13:01:05,869 [MyQrtzScheduler_Worker-1] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' is being obtained: MyQrtzScheduler_Worker-1
    2015-01-29 13:01:05,872 [MyQrtzScheduler_Worker-1] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' given to: MyQrtzScheduler_Worker-1
    2015-01-29 13:01:05,880 [MyQrtzScheduler_Worker-1] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' returned by: MyQrtzScheduler_Worker-1
    2015-01-29 13:01:05,915 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
    2015-01-29 13:01:05,917 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' is desired by: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:01:05,918 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' is being obtained: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:01:05,921 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' given to: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:01:05,954 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.impl.jdbcjobstore.StdRowLockSemaphore - Lock 'TRIGGER_ACCESS' returned by: MyQrtzScheduler_QuartzSchedulerThread
    2015-01-29 13:01:05,955 [MyQrtzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'node1_1422543657050.Job2', class=com.mycompany.myapp.jobs.Job2
    2015-01-29 13:01:05,961 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingTriggerHistoryPlugin - Trigger node1_1422543657050.Job2Trigger fired job node1_1422543657050.Job2 at:  13:01:05 01/29/2015
    2015-01-29 13:01:05,962 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingJobHistoryPlugin - Job node1_1422543657050.Job2 fired (by trigger node1_1422543657050.Job2Trigger) at:  13:01:05 01/29/2015
    2015-01-29 13:01:05,963 [MyQrtzScheduler_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job node1_1422543657050.Job2
    2015-01-29 13:01:05,963 [MyQrtzScheduler_Worker-1]  WARN com.mycompany.myapp.jobs.Job2 - No outbound files found; Outbound File SLA Job cannot check for SLA breaches.
    2015-01-29 13:01:05,965 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingJobHistoryPlugin - Job node1_1422543657050.Job2 execution complete at  13:01:05 01/29/2015 and reports: null
    2015-01-29 13:01:05,966 [MyQrtzScheduler_Worker-1]  INFO org.quartz.plugins.history.LoggingTriggerHistoryPlugin - Trigger node1_1422543657050.Job2Trigger completed firing job node1_1422543657050.Job2 at  13:01:05 01/29/2015 with resulting trigger instruction code: DO NOTHING

【问题讨论】:

标签: java oracle cluster-computing quartz-scheduler


【解决方案1】:

OP给出了以下答案。

问题是我定义了具有唯一组 id(调度程序 id)的身份的石英作业,而不是集群中所有主机共有的组 id。由于调度程序 id 对主机来说是唯一的,因此集群中的每个主机都会使用完全限定的作业名称 groupId.jobName 来查看该作业是否已经存在,并且肯定会发现它不存在,因此它将创建一个新的实例Job1 和 Job2 在启动期间。如果没有 Java 中的明确请求或 Oracle 中的手动 sql 语句,石英作业/触发器永远不会过期或清除。因此,随着时间的推移,实例会逐渐增加,而不是让石英运行 Job1 和 Job2 的单个实例,而是运行随时间创建的每个作业的所有实例(因此多次执行和多个电子邮件警报)。

解决办法是,在定义作业的身份时,我将 schedulerId 替换为“MyQuartzJobs”等静态字符​​串。

基本上,我更改了以下 Java 代码行:

JobDetail job = 
newJob(Job1.class).withIdentity(JOB1_JOB_NAME,  uniqueSchedulerId)
.withDescription(JOB1_DESC + " created [" + new Date() + "]")
.storeDurably(false)
.requestRecovery(false)
.build();

类似于以下内容:

JobDetail job = 
newJob(Job1.class).withIdentity(JOB1_JOB_NAME,  "MyQuartzJobs")
.withDescription(JOB1_DESC + " created [" + new Date() + "]")
.storeDurably(false)
.requestRecovery(false)
.build();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    相关资源
    最近更新 更多