Java 重新启动quartz计划程序而不出现错误
上下文 我正在尝试使用jdbc在集群模式下使用quartz调度程序 问题 在集群模式下使用jdbc之前,我只是使用RAM存储测试了调度器。这没有问题,我能够重新启动调度程序(主类),没有任何错误。我现在遇到的问题是,当我停止执行(ctrl+c)然后重新启动时,总是会收到错误消息:Java 重新启动quartz计划程序而不出现错误,java,quartz-scheduler,Java,Quartz Scheduler,上下文 我正在尝试使用jdbc在集群模式下使用quartz调度程序 问题 在集群模式下使用jdbc之前,我只是使用RAM存储测试了调度器。这没有问题,我能够重新启动调度程序(主类),没有任何错误。我现在遇到的问题是,当我停止执行(ctrl+c)然后重新启动时,总是会收到错误消息: org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'MyTestJob', because one already exists with t
org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'MyTestJob', because one already exists with this identification.
我不明白这里发生了什么。quartz不支持重新启动计划程序吗?我的意思是,如果发生崩溃,并且计划程序在恢复后重新启动,会发生什么?是从quartz数据库中删除作业的唯一选项吗?也许还有另一种方法或者我错过了什么。我觉得使用一个不能处理重启的库不是很舒服
另一件奇怪的事情是,当切换到jdbc时,我的作业不再被触发,我只看到数据库中等待的状态。这会是什么?作业(cron计划)在RAM模式下正常工作
对于这个简单任务中遇到的文档级别和问题,我感到有点惊讶,因为我已经听说quartz调度器很多年了,但从未使用过它。古德建议,我不是唯一一个有这个问题的人。我希望这只是我的问题,并且我的问题有一个简单的解决方案,否则在2.2.x版本中第一次尝试这个库,并且已经不得不寻找其他东西,这将是非常令人失望的
以下是我的配置:
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.skipUpdateCheck = true
org.quartz.scheduler.instanceName = Test-Scheduler
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.StdJDBCDelegate
org.quartz.jobStore.useProperties = true
org.quartz.jobStore.dataSource = quartzDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
这是我的密码:
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
scheduler.start();
JobDetail jobDetail = newJob(job.getClass())
.withIdentity("test-name", "test-group")
.build();
CronTrigger trigger = newTrigger()
.withIdentity("test-name-trigger", "test-group")
.withSchedule(cronSchedule("0 0/1 * * * ?"))
.build();
scheduler.scheduleJob(jobDetail, trigger);
System.out.println(trigger.getNextFireTime());
编辑
这很有趣
1) RAM模式有效
2) 启用集群的jdbc无法工作,并且(几乎)以静默方式失败-即使启用了日志记录。在日志输出中,我看到以下内容:
19:57:29,913 INFO StdSchedulerFactory:1184 - Using default implementation for ThreadExecutor
19:57:29,936 INFO SchedulerSignalerImpl:61 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
19:57:29,936 INFO QuartzScheduler:240 - Quartz Scheduler v.2.2.1 created.
19:57:29,938 INFO JobStoreTX:667 - Using db table-based data access locking (synchronization).
19:57:29,940 INFO JobStoreTX:59 - JobStoreTX initialized.
19:57:29,941 INFO QuartzScheduler:305 - Scheduler meta-data: Quartz Scheduler (v2.2.1) 'Test-Scheduler' with instanceId 'Michael-PC1405447049916'
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 25 threads.
Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is clustered.
19:57:29,941 INFO StdSchedulerFactory:1339 - Quartz scheduler 'Test-Scheduler' initialized from default resource file in Quartz package: 'quartz.properties'
19:57:29,941 INFO StdSchedulerFactory:1343 - Quartz scheduler version: 2.2.1
19:57:29,995 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hgeby993gf1xpdmdc44s|7ec4d0, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hgeby993gf1xpdmdc44s|7ec4d0, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/scheduler, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> SELECT 1 FROM QRTZ_JOB_DETAILS, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
19:57:30,243 DEBUG StdRowLockSemaphore:107 - Lock 'TRIGGER_ACCESS' is desired by: main
19:57:30,262 DEBUG StdRowLockSemaphore:92 - Lock 'TRIGGER_ACCESS' is being obtained: main
19:58:21,328 DEBUG StdRowLockSemaphore:141 - Lock 'TRIGGER_ACCESS' was not obtained by: main - will try again.
19:58:22,329 DEBUG StdRowLockSemaphore:92 - Lock 'TRIGGER_ACCESS' is being obtained: main
19:59:13,389 DEBUG StdRowLockSemaphore:141 - Lock 'TRIGGER_ACCESS' was not obtained by: main - will try again.
19:59:14,389 DEBUG StdRowLockSemaphore:92 - Lock 'TRIGGER_ACCESS' is being obtained: main
尽管如此,就在我即将再次启用群集模式时,我看到了异常:
Exception in thread "main" org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: Lock wait timeout exceeded; try restarting transaction [See nested exception: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction]
at org.quartz.impl.jdbcjobstore.StdRowLockSemaphore.executeSQL(StdRowLockSemaphore.java:157)
at org.quartz.impl.jdbcjobstore.DBSemaphore.obtainLock(DBSemaphore.java:113)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3780)
at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.clearAllSchedulingData(JobStoreSupport.java:1956)
at org.quartz.core.QuartzScheduler.clear(QuartzScheduler.java:1572)
at org.quartz.impl.StdScheduler.clear(StdScheduler.java:239)
at com.scs.core.cron.TaskRunner.main(TaskRunner.java:52)
20:04:15,993 DEBUG SimpleSemaphore:132 - Lock 'TRIGGER_ACCESS' retuned by: main
20:04:15,993 DEBUG JobStoreTX:703 - JobStore background threads started (as scheduler was started).
20:04:15,994 INFO QuartzScheduler:575 - Scheduler Test-Scheduler_$_NON_CLUSTERED started.
20:04:15,994 DEBUG JobStoreTX:3933 - MisfireHandler: scanning for misfires...
20:04:16,000 DEBUG JobStoreTX:3182 - Found 0 triggers that missed their scheduled fire-time.
20:04:16,004 DEBUG QuartzSchedulerThread:276 - batch acquisition of 0 triggers
20:04:16,008 DEBUG SimpleSemaphore:81 - Lock 'TRIGGER_ACCESS' is desired by: main
20:04:16,008 DEBUG SimpleSemaphore:88 - Lock 'TRIGGER_ACCESS' is being obtained: main
20:04:16,008 DEBUG SimpleSemaphore:105 - Lock 'TRIGGER_ACCESS' given to: main
20:04:16,052 DEBUG SimpleSemaphore:132 - Lock 'TRIGGER_ACCESS' retuned by: main
Found job: class to.test.cron.ImportProducts
Tue Jul 15 20:05:00 CEST 2014
isStarted=true
isShutdown=false
isInStandbyMode=false
20:04:16,058 DEBUG QuartzSchedulerThread:276 - batch acquisition of 0 triggers
20:04:42,961 ERROR ErrorLogger:2425 - An error occurred while scanning for the next triggers to fire.
org.quartz.JobPersistenceException: Couldn't acquire next trigger: to.test.cron.ImportProducts [See nested exception: java.lang.ClassNotFoundException: to.test.cron.ImportProducts]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2848)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2759)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2757)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3787)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2756)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:272)
Caused by: java.lang.ClassNotFoundException: to.test.cron.ImportProducts
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.quartz.simpl.InitThreadContextClassLoadHelper.loadClass(InitThreadContextClassLoadHelper.java:72)
at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:114)
at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:138)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2816)
... 5 more
3) 在禁用集群的jdbc模式下,它也不起作用,但我得到一个异常:
Exception in thread "main" org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: Lock wait timeout exceeded; try restarting transaction [See nested exception: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction]
at org.quartz.impl.jdbcjobstore.StdRowLockSemaphore.executeSQL(StdRowLockSemaphore.java:157)
at org.quartz.impl.jdbcjobstore.DBSemaphore.obtainLock(DBSemaphore.java:113)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3780)
at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.clearAllSchedulingData(JobStoreSupport.java:1956)
at org.quartz.core.QuartzScheduler.clear(QuartzScheduler.java:1572)
at org.quartz.impl.StdScheduler.clear(StdScheduler.java:239)
at com.scs.core.cron.TaskRunner.main(TaskRunner.java:52)
20:04:15,993 DEBUG SimpleSemaphore:132 - Lock 'TRIGGER_ACCESS' retuned by: main
20:04:15,993 DEBUG JobStoreTX:703 - JobStore background threads started (as scheduler was started).
20:04:15,994 INFO QuartzScheduler:575 - Scheduler Test-Scheduler_$_NON_CLUSTERED started.
20:04:15,994 DEBUG JobStoreTX:3933 - MisfireHandler: scanning for misfires...
20:04:16,000 DEBUG JobStoreTX:3182 - Found 0 triggers that missed their scheduled fire-time.
20:04:16,004 DEBUG QuartzSchedulerThread:276 - batch acquisition of 0 triggers
20:04:16,008 DEBUG SimpleSemaphore:81 - Lock 'TRIGGER_ACCESS' is desired by: main
20:04:16,008 DEBUG SimpleSemaphore:88 - Lock 'TRIGGER_ACCESS' is being obtained: main
20:04:16,008 DEBUG SimpleSemaphore:105 - Lock 'TRIGGER_ACCESS' given to: main
20:04:16,052 DEBUG SimpleSemaphore:132 - Lock 'TRIGGER_ACCESS' retuned by: main
Found job: class to.test.cron.ImportProducts
Tue Jul 15 20:05:00 CEST 2014
isStarted=true
isShutdown=false
isInStandbyMode=false
20:04:16,058 DEBUG QuartzSchedulerThread:276 - batch acquisition of 0 triggers
20:04:42,961 ERROR ErrorLogger:2425 - An error occurred while scanning for the next triggers to fire.
org.quartz.JobPersistenceException: Couldn't acquire next trigger: to.test.cron.ImportProducts [See nested exception: java.lang.ClassNotFoundException: to.test.cron.ImportProducts]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2848)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2759)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2757)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3787)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2756)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:272)
Caused by: java.lang.ClassNotFoundException: to.test.cron.ImportProducts
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.quartz.simpl.InitThreadContextClassLoadHelper.loadClass(InitThreadContextClassLoadHelper.java:72)
at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:114)
at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:138)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2816)
... 5 more
我不太明白为什么我在3种不同的模式下会有3种完全不同的行为。如果这个类可以在RAM模式下找到,为什么它不能在jdbc模式下找到呢?为什么不以群集模式登录?该类实际上位于osgi类型的模块中。这会导致问题吗(在jdbc模式下)?有什么我可以做的,以便类可以找到,如传递类加载器等石英
我现在很迷路,非常感谢你的帮助。如果不得不回到标准的cron工作岗位上,那将是一种耻辱,尤其是在quartz有如此多的工作可以提供的情况下
提前感谢您提供的任何帮助
Michael这是一个持久性工作存储的一般“问题”。您的应用程序显然试图添加作业存储中已经存在的作业,因为您的应用程序过去已经添加了该作业。您有两个选择:
希望这能有所帮助。谢谢你的提示。这似乎暂时停止了我的错误(提示1),并将作为一个开始。稍后我将使用#2进行改进。对于我的另一个问题,你可能有什么建议吗。当我处于RAM模式时,我的任务每分钟都在执行,但在添加quartz.properties和jdbc配置后,我可以看到正在db中创建作业,但它不再被触发。“trigger.getNextFireTime()”也返回正确的时间。在DB中,prev_fire_time保持为-1。我将首先仔细检查调度程序是否已实际启动(即,scheduler.isStarted()返回true)。如果这不能解决问题,那么应该在应用程序的日志配置中启用“org.quartz”类别的日志记录。如果这没有告诉您任何事情,您将不得不调试QuartzSchedulerThread以查看发生了什么。好的,看起来我需要进一步挖掘:isStarted=true,IsShutton=false,isInStandbyMode=false(3),看起来Quartz无法加载作业类。Quartz API是否由加载作业类的类加载器加载?这些错误通常发生在共享应用服务器类加载器(例如Tomcat的公共类加载器)加载Quartz API时,该类加载器在部署的应用程序(例如WEB-INF/classes、WEB-INF/lib)中没有看到绑定的作业类。Quartz在加载类(例如作业详细信息)时支持多种策略-请参阅org.Quartz.scheduler.classLoadHelper.classquartz属性。没问题。我们使用我们自己的产品做到这一点:-)请查看QuartzDesk(www.QuartzDesk.com)。即使是Lite(免费)版也允许您在常规计划之外临时执行作业。