我在Quartz中看到一个奇怪的行为,当它在群集模式下配置时,spring被配置为overwriteExistingJobs=true
。
我的问题是:我的配置有问题吗?可以在群集模式下使用overwriteExistingJobs吗?或者这是Quartz中的一个错误? (因为quartz应该提供集群作业仅在一个节点中运行的不变量)
我有一个每秒触发的SimpleTrigger,它会触发一个用@DisallowConcurrentExecution
注释的作业,并打印触发器触发的次数。问题显示我运行时运行应用程序的第二个实例;在这种情况下,使用不同的触发器计数在两个实例上触发作业(我可以在数据库中看到有不同值的更新将转到qrtz_simple_triggers.times_triggered
。
当我设置属性overwriteExistingJobs=false
时,quartz会按预期运行,并且作业仅在群集的一个实例中运行。
我正在使用
这是我的弹簧配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/quartz" />
<property name="username" value="quartz" />
<property name="password" value="quartz" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="myJobDetails" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="og.test.MyJob"/>
<property name="durability" value="true"/>
<property name="name" value="myJobDetails"/>
<property name="group" value="myJobDetails"/>
</bean>
<bean id="myJobDetailsSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="myJobDetails"/>
<property name="startDelay" value="2000"/>
<property name="repeatInterval" value="1000"/>
<property name="name" value="myJobDetailsSimpleTrigger"/>
<property name="group" value="myJobDetails"/>
</bean>
<bean id="scheduler" class="og.test.TriggerCleaningSchedulerFactoryBean">
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">MY_JOB_SCHEDULER</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">10</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
</props>
</property>
<property name="dataSource" ref="dataSource"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="overwriteExistingJobs" value="true"/> <!-- offending property -->
<property name="schedulerName" value="quartzScheduler"/>
<property name="autoStartup" value="true"/>
<property name="triggers">
<list><ref bean="myJobDetailsSimpleTrigger"/></list>
</property>
<property name="jobDetails">
<list><ref bean="myJobDetails" /></list>
</property>
</bean>
</beans>
我的工作班
@DisallowConcurrentExecution
public class MyJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
String jobName = ctx.getJobDetail().getKey().getName();
String triggerName = ctx.getTrigger().getKey().getName();
SimpleTrigger simpleTrigger = (SimpleTrigger) ctx.getTrigger();
int timesTriggered = simpleTrigger.getTimesTriggered();
System.out.printf("%d - %s/%s - %d\n", System.currentTimeMillis(), jobName, triggerName, timesTriggered);
}
}