在测试和生产环境一般服务器的部署不会少于2台。这时定时任务的配置问题尤其重要,因为定时任务只需要跑一次。
有的公司采用的做法是,单独一台服务器部署跑批服务,其他服务器提供其他业务服务。另外的一种做法是使用quartz集群。
本文将介绍spring mvc框架中quartz集群的搭建方法。
maven项目中增加quartz依赖,
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
在src目录下(maven项目在src/main/resources下)增加quartz.properties(必须是这个名字)文件,文件内容如下:
#==============================================================
#Configure Main Scheduler Properties
#==============================================================
org.quartz.scheduler.instanceName = clusterScheduler
org.quartz.scheduler.instanceId = AUTO
#==============================================================
#Configure JobStore
#==============================================================
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.maxMisfiresToHandleAtATime = 1
org.quartz.jobStore.misfireThreshold = 120000
org.quartz.jobStore.txIsolationLevelSerializable = true
#==============================================================
#Configure DataSource
#==============================================================
#org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
#org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8
#org.quartz.dataSource.myDS.user = root
#org.quartz.dataSource.myDS.password = root
#org.quartz.dataSource.myDS.maxConnections = 30
org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
#==============================================================
#Configure ThreadPool
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#==============================================================
#Skip Check Update
#update:true
#not update:false
#==============================================================
org.quartz.scheduler.skipUpdateCheck = true
#============================================================================
Configure Plugins
#============================================================================
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true
在数据库中导入quartz集群需要的表,这些信息可以从quartz官网下载一个quartz.version.tar.gz, 解压后在doc/dbTables中,找到你数据库的相关文件,
比如mysql可以用 tables_mysql.sql . 导入数据库。
在spring配置文件中定义quartz相关bean和任务
<bean id="clusterJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.lcg.demo.job.MyDetailQuartzJobBean" />
<!-- fail-over 重写执行失败的任务,default=false -->
<property name="requestsRecovery" value="false"/>
<property name="durability" value="true" />
</bean>
<!-- 定期动态创建数据表 -->
<bean id="clusterTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="clusterJob"/>
<property name="cronExpression" value="0/5 * * * * ?"/>
</bean>
MyJobFactory (保证spring注入成功)
package com.lcg.demo.job;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
public class MyJobFactory extends org.springframework.scheduling.quartz.SpringBeanJobFactory
{
@Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
beanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
MyDetailQuartzJobBean (任务类)
package com.lcg.demo.job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.lcg.demo.service.DataCenterService;
public class MyDetailQuartzJobBean extends QuartzJobBean{
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private DataCenterService dataCenterService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("集群任务开始");
this.dataCenterService.doMyTask();
}
// 供bean初始化时使用 bean init-method (tomcat启动时会执行)
public void initFun(){
logger.info("集群任务开始");
this.dataCenterService.doMyTask();
}
}
至此完成。
可以将项目打包,同时发布到2个tomcat进行测试。
(测试方法:job里面调用service往表里写数据,带一列为时间。)