quartz集群搭建(整合spring)
来源:互联网 发布:极限挑战知乎话题 编辑:程序博客网 时间:2024/06/05 19:32
本文记录搭建quartz集群的过程和遇到的各种坑:
搭建又单节点到集群搭建非常简单,步骤以官网为准
主要内容就是添加了quartz.properties 文件,并修改org.quartz.jobStore.class属性(集群搭建依赖于数据库,不能再用RAMStore)
我的配置见代码:
#============================================================================# Configure Main Scheduler Properties#============================================================================org.quartz.scheduler.instanceName=schedulesorg.quartz.scheduler.instanceId=AUTOorg.quartz.scheduler.skipUpdateCheck=true#============================================================================# Configure ThreadPool#============================================================================org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount=5org.quartz.threadPool.threadPriority=5#============================================================================# Configure JobStore#============================================================================org.quartz.jobStore.misfireThreshold=60000org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX##org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。 ##因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。 ##这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。 org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.dataSource=myDSorg.quartz.jobStore.tablePrefix=QRTZ_org.quartz.jobStore.isClustered=true##org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。 ##Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。 ##通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。 org.quartz.jobStore.clusterCheckinInterval = 20000#============================================================================# Configure Datasources#============================================================================org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driverorg.quartz.dataSource.myDS.URL=@QUARTZ_DB_URL@org.quartz.dataSource.myDS.user=@QUARTZ_DB_USER@org.quartz.dataSource.myDS.password=@QUARTZ_DB_PASSWORD@org.quartz.dataSource.myDS.maxConnections=5org.quartz.dataSource.myDS.validationQuery=select 0
在scheduler.xml中添加标红的内容,支出quartz配置文件的位置。scheduler.xml的其他内容下文再详解
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans> <bean id="tarzanDumpTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail"> <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="durability" value="true" /> <property name="requestsRecovery" value="true" /> <property name="name" value="tarzanDump"/> <property name="jobClass"> <value>com.my.scheduler.MyDetailQuartzJobBean</value> </property> <property name="jobDataAsMap"> <map> <entry key="targetObject" value="tarzanDump" /> <entry key="targetMethod" value="execute" /> </map> </property> </bean> </property> <property name="cronExpression" value="0 0 3 * * ? *"></property> </bean> <bean id="cacheJamEnrollNumTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail"> <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="durability" value="true" /> <property name="requestsRecovery" value="true" /> <property name="name" value="cacheJamEnrollNum"/> <property name="jobClass"> <value>com.my.scheduler.MyDetailQuartzJobBean</value> </property> <property name="jobDataAsMap"> <map> <entry key="targetObject" value="cacheJamEnrollNum" /> <entry key="targetMethod" value="execute" /> </map> </property> </bean> </property> <property name="cronExpression" value="0 0/10 * * * ? * "/> </bean> <bean id="SpringJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="tarzanDumpTrigger"/> <ref bean="cacheJamEnrollNumTrigger"/> </list> </property> <property name="applicationContextSchedulerContextKey" value="applicationContext" /> <property name="configLocation" value="./WEB-INF/quartz.properties"/> </bean></beans>
可以看到,跟单节点配置几乎没有太多的区别。但是你会发现,里面的坑很多。一一说起
spring创建JobDetail的定时任务有两种方式:
第一种方式是利用Spring封装的Quartz类进行特定方法的实现,第二种是通过透明的使用Quartz达到定时任务开发的目的,总体说第二种对开发人员更方便!
配置Spring的任务调度抽象层简化了任务调度,在Quartz的基础上提供了更好的调度对象。Spring使用Quartz框架来完成任务调度,创建Quartz的作业Bean(JobDetail),有一下两种方法:
1:利用JobDetailBean包装QuartzJobBean子类(即Job类)的实例。
2:利用MethodInvokingJobDetailFactoryBean工厂Bean包装普通的Java对象(即Job类)。
说明:
1:采用第一种方法 创建job类,一定要继承QuartzJobBean ,实现 executeInternal(JobExecutionContextjobexecutioncontext)方法,此方法就是被调度任务的执行体,然后将此Job类的实例直接配置到JobDetailBean中即可。这种方法和在普通的Quartz编程中是一样的。
2:采用第二种方法 创建Job类,无须继承父类,直接配置MethodInvokingJobDetailFactoryBean即可。但需要指定一下两个属性:
targetObject:指定包含任务执行体的Bean实例。
targetMethod:指定将指定Bean实例的该方法包装成任务的执行体。
第二种情况下,因为spring的methodInvoker不可序列化,没有办法在持久化到数据库中,被我先抛弃了(网上也是有解决办法的,我没有仔细去看,采用了第一种方式)
我们可以这样配置:
<bean id="cronTriggerPunch" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <!-- 使用嵌套Bean的方式来定义任务Bean --> <bean class="org.springframework.scheduling.quartz.JobDetailBean"> <!-- 指定任务Bean的实现类 --> <property name="jobClass" value="com.my.MyJob"/><!-- MyJob需要集成QuartzJobBean --> </property> <!-- 指定Cron表达式:周一到周五7点、12点执行调度 --> <property name="cronExpression" value="0 0 7,12 ? * MON-FRI"/> </bean>这种情况下,JobDetailBean里必须要指定jobClass这个属性。
可能有这样两种情况,
1.我们的一个其他组件需要用到一个MyJob的实例,这种情况下,我们可能期望把MyJob交给spring来管理,而在JobDetailBean中只是指向spring中的这个bean就好了
2.MyJob中的某些属性不能序列化。
如果只是第一种情况的话,可以用封装来解决问题。第二个问题就不是那么好办了。有些属性是真的没有办法被实例化或者代价很大。
下面介绍种解决方法:
自己定义一个MyJobBean继承QuartzJobBean
public class MyJobBean extends QuartzJobBean{ private static final Logger LOG = Logger.getLogger(MyJobBean.class); private String targetObject; private String targetMethod; private ApplicationContext ctx; @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { Object otargetObject = ctx.getBean(targetObject); Method m = null; try { m = otargetObject.getClass().getDeclaredMethod(targetMethod); m.invoke(otargetObject); } catch (SecurityException e) { LOG.error(e.getMessage(),e); } catch (NoSuchMethodException e) { LOG.error(e.getMessage(),e); } } catch (Exception e) { throw new JobExecutionException(e); } } public void setApplicationContext(ApplicationContext applicationContext) { this.ctx = applicationContext; } public void setTargetObject(String targetObject) { this.targetObject = targetObject; } public void setTargetMethod(String targetMethod) { this.targetMethod = targetMethod; }}
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans> <bean id="tarzanDump" class="com.my.TarzanDump"/> <bean id="tarzanDumpTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail"> <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="durability" value="true" /> <property name="requestsRecovery" value="true" /> <property name="name" value="tarzanDump"/> <property name="jobClass"> <value>com.my.scheduler.MyDetailQuartzJobBean</value> </property> <property name="jobDataAsMap"> <map> <entry key="targetObject" value="tarzanDump" /> <entry key="targetMethod" value="execute" /> </map> </property> </bean> </property> <property name="cronExpression" value="0 0 3 * * ? *"></property> </bean> <bean id="cacheJamEnrollNumTrigger" class="com.my.cacheJamEnrollNumTrigger"/> <bean id="cacheJamEnrollNumTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail"> <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="durability" value="true" /> <property name="requestsRecovery" value="true" /> <property name="name" value="cacheJamEnrollNum"/> <property name="jobClass"> <value>com.my.scheduler.MyDetailQuartzJobBean</value> </property> <property name="jobDataAsMap"> <map> <entry key="targetObject" value="cacheJamEnrollNum" /> <entry key="targetMethod" value="execute" /> </map> </property> </bean> </property> <property name="cronExpression" value="0 0/10 * * * ? * "/> </bean> <bean id="SpringJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="tarzanDumpTrigger"/> <ref bean="cacheJamEnrollNumTrigger"/> </list> </property> <property name="applicationContextSchedulerContextKey" value="applicationContext" /> <property name="configLocation" value="./WEB-INF/quartz.properties"/> </bean></beans>
这种情况下tarzanDum和cacheJamEnrollNum这些bean都是在spring中管理,在MyJobBean从spring中获取到这些bean,并反射出来调用在scheduler.xml里指定的方法。可以解决上述的两个难题。
但是你会发现,数据库里的jobDetail序列化的实际上只是MyJobBean这个类的实例,并不涉及真正的job(tarzanDump和cacheJamEnrollNum)。当quartz节点从数据库里取到MyJobBean的时候,再向spring中请求获得相应的bean和方法。
- quartz集群搭建(整合spring)
- Quartz学习5:Spring整合Quartz在集群中的应用
- redis集群搭建以及和spring整合
- Redis集群搭建以及Spring整合
- Spring-----Spring整合Quartz
- Spring+Quartz tomcat集群
- Spring+quartz集群配置
- Spring+Quartz tomcat集群
- spring+quartz集群1
- Spring+Quartz 集群2
- spring quartz 集群配置
- spring+Quartz集群
- spring quartz 集群 注意
- spring quartz集群
- spring+mybatis+quartz集群
- [java]spring-Quartz集群
- spring quartz集群配置
- spring整合quartz
- (解题报告)HDU2001---计算两点间的距离
- block
- iOS不同版本适配问题
- Putty的颜色
- 10种排序算法
- quartz集群搭建(整合spring)
- Cadence初学手记(转)
- 程序阻碍OD调试的方式2
- Hadoop常见错误及解决办法
- 《Kafka 0.9.0 Documentation》----Design
- HDU2002---计算球体积
- Android的Sqlite中DateTime类型数据的存取问题
- 14.7.1 Enabling File Formats
- 用instanceof判断参数是否是给定的类型