〇、前言
使用SPRING的定时任务框架,如果是在分布式的环境下,由于有多台节点,会产生相同的任务,会被多个节点执行,这时需引入分布式的QUARTZ。
一、Quartz集群部署实践
Quartz与Spring结合使用,Spring通过提供org.springframework.scheduling.quartz下的封装类对Quartz支持。
Quartz集群部署:
Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点。该集群需要分别对每个节点分别启动或停止,不像应用服务器的集群,独立的Quartz节点并不与另一个节点或是管理节点通信。Quartz应用是通过数据库表来感知到另一应用。只有使用持久的JobStore才能完成Quqrtz集群。
二、基于Sping的集群配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<beans>
<bean id="sampleJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="sampleJobDetail" />
<property name="cronExpression" value="0 0/1 * * * ?" />
</bean>
<bean id="sampleJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.feng.ini.modules.trd.quartz.SampleJob"/>
<property name="durability" value="true" />
</bean>
<!-- 调度工厂 -->
<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置属性 -->
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">OrderScheduler</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<!-- 线程池配置 -->
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">5</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
<!-- 集群配置 -->
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop>
<prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop>
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
</props>
</property>
<property name="schedulerName" value="OrderScheduler" />
<!-- QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->
<property name="startupDelay" value="30" />
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<!-- QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->
<property name="overwriteExistingJobs" value="true" />
<!-- 自动启动 -->
<property name="autoStartup" value="true" />
<!-- 注册触发器 -->
<property name="triggers">
<list>
<ref bean="sampleJobTrigger" />
</list>
</property>
<!-- 注册任务详情 -->
<property name="jobDetails">
<list>
<ref bean="sampleJobDetail" />
</list>
</property>
<!-- 注册任务调度监听器 -->
<property name="schedulerListeners">
<list></list>
</property>
</bean>
</beans>
</beans>
三、添加Job类
package com.feng.ini.modules.trd.quartz;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import xin.ini.common.utils.DateUtils;
public class SampleJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("job-1:" + DateUtils.formatDateTime(new Date()) + "," + context.getFireInstanceId() + "," + context.getJobDetail().getClass().getName());
}
}
四、分布式部署多个任务
为了测试,在同一个Tomcat中部署了4个任务,分别为job-1、2、3、4,以下是执行结果:
job-2:2016-05-28 16:23:00,Yuk14644237475091464423747488,org.quartz.impl.JobDetailImpl
job-3:2016-05-28 16:24:00,Yuk14644237583351464423758320,org.quartz.impl.JobDetailImpl
job-4:2016-05-28 16:25:00,Yuk14644237689031464423768887,org.quartz.impl.JobDetailImpl
job-4:2016-05-28 16:26:00,Yuk14644237689031464423768888,org.quartz.impl.JobDetailImpl
job-1:2016-05-28 16:27:00,Yuk14644238098361464423809814,org.quartz.impl.JobDetailImpl
job-2:2016-05-28 16:28:00,Yuk14644237475091464423747489,org.quartz.impl.JobDetailImpl
job-3:2016-05-28 16:29:00,Yuk14644237583351464423758321,org.quartz.impl.JobDetailImpl
job-4:2016-05-28 16:30:00,Yuk14644237689031464423768889,org.quartz.impl.JobDetailImpl
job-3:2016-05-28 16:31:00,Yuk14644237583351464423758322,org.quartz.impl.JobDetailImpl
job-2:2016-05-28 16:32:00,Yuk14644237475091464423747490,org.quartz.impl.JobDetailImpl
job-4:2016-05-28 16:33:00,Yuk14644237689031464423768890,org.quartz.impl.JobDetailImpl
job-3:2016-05-28 16:34:00,Yuk14644237583351464423758323,org.quartz.impl.JobDetailImpl
job-1:2016-05-28 16:35:00,Yuk14644238098361464423809815,org.quartz.impl.JobDetailImpl
job-4:2016-05-28 16:36:00,Yuk14644237689031464423768891,org.quartz.impl.JobDetailImpl
job-3:2016-05-28 16:37:00,Yuk14644237583351464423758324,org.quartz.impl.JobDetailImpl
job-2:2016-05-28 16:38:00,Yuk14644237475091464423747491,org.quartz.impl.JobDetailImpl
job-1:2016-05-28 16:39:00,Yuk14644238098361464423809816,org.quartz.impl.JobDetailImpl
job-4:2016-05-28 16:40:00,Yuk14644237689031464423768892,org.quartz.impl.JobDetailImpl
从结果可以看出,同一时刻,只执行了一个任务,而且是4个任务都是随机执行。
五、参考资料
http://tech.meituan.com/mt-crm-quartz.html?utm_source=tuicool&utm_medium=referral Quartz应用与集群原理分析
http://www.blogjava.net/paulwong/archive/2014/11/14/420104.html 分布式调度QUARTZ+SPRING
http://blog.csdn.net/evankaka/article/details/45361759 【Quartz】深入Job、JobDetail、JobDataMap、Trigger