Spring quartz在集群环境下解决方案
一,前言
多台服务器上各有一个 QUARTZ ,他们会按照指定的 SCHEDULE 自动执行各自的任务。在网上看了很多关于quartz的资料和讨论,尤其是关于quartz和集群应用的讨论是非常的激烈,很多人都共享了自己的想法,如:http://www.iteye.com/topic/114965,这位仁兄的观点比较有道理,其实我的解决方案就是文中的第三种观点,quartz本身事实上也是支持集群的。
二,实现原理
基于数据库引擎及
High-Available
的策略(
集群的一种策略
)自动协调每个节点的
QUARTZ
,当任一一节点的
QUARTZ
非正常关闭或出错时,另几个节点的
QUARTZ
会自动启动;
cluster上的每一个node都在跑quartz,然后也是通过数据中记录的状态来判断这个操作是否正在执行,这就要求cluster上所有的node的时间应该是一样的。而且每一个node都跑应用就意味着每一个node都需要有自己的线程池来跑quartz
三,本方案的优点
1. 每台作为集群点的 APP SERVER 上都可以布署 QUARTZ ;
2. QUARTZ 的 TASK ( 12 张表)实例化如数据库,基于数据库引擎及 High-Available
的策略(集群的一种策略)自动协调每个节点的 QUARTZ ,当任一一节点的 QUARTZ 非正常关闭或出错时,另几个节点的 QUARTZ 会自动启动;
3. 无需开发人员更改原已经实现的 QUARTZ ,使用 SPRING+ 类反射的机制对原有程序作切面重构;
4. 不同的node可能会执行的不同的定时任务,这个要看服务器的时间设定了,可能node1执行一个任务,此时node2会执行另一个任务,这样做会比较好的做到负载均衡,而且也能比较好的做到容错,一个node挂了,不会
影响到其他node上的定时任务。每个node上的quartz定期的向数据库里登记它们的时间,如果某个实例在一定的时间内没有登记,就表示这个实例挂了 ,其它的实例就会重新获取这个挂了的实例所执行的任务
四,方案实现过程
1. 把 QUARTZ 的 TASK 实例化进数据库, QUARTZ
只有实例化进入数据库后才能做集群,外面的解决方案说实例化在内存里全部是错的,把quartz-1.8.4/docs/dbTables/tables_oracle.sql在
ORACLE9I2 及以上版本中执行一下会生成 12 张表;
2. 重写MethodInvokingJobDetailFactoryBean
,这个
MethodInvokingJobDetailFactoryBean
类中的
methodInvoking
方法,是不支持序列化的,因此在把
QUARTZ
的
TASK
序列化进入数据库时就会抛错。网上有说把
SPRING
源码拿来,修改一下这个方案,然后再打包成
SPRING.jar
发布,这些都是不好的方法,是不安全的。
必须根据
QuartzJobBean
来重写一个自己的类,然后使用
SPRING
把这个重写的类(我们就名命它为:
MyDetailQuartzJobBean
)注入
appContext
中后,再使用
AOP
技术反射出原有的
quartzJobx(
就是开发人员原来已经做好的用于执行
QUARTZ
的
JOB
的执行类
)
。
下面来看
MyDetailQuartzJobBean
类:
public class MyDetailQuartzJobBean extends
QuartzJobBean {
protected final Log logger =
LogFactory.getLog(getClass());
private String
targetObject;
private String
targetMethod;
private ApplicationContext
ctx;
protected void
executeInternal(JobExecutionContext context)
throws JobExecutionException {
try {
logger.info("execute [" + targetObject + "] at
once>>>>>>");
Object otargetObject = ctx.getBean(targetObject);
Method m = null;
try {
m = otargetObject.getClass().getMethod(targetMethod,
new Class[] {});
m.invoke(otargetObject, new Object[] {});
} catch (SecurityException e) {
logger.error(e);
} catch (NoSuchMethodException e) {
logger.error(e);
}
} catch
(Exception e) {
throw new JobExecutionException(e);
}
}
2. 生成 quartz.properties 文件,把它放在工程的 src 目录下,使其能够被编译时纳入 class
path 。
quartz.properties
文件的内容
:
#==============================================================
#Configure Main Scheduler Properties
#==============================================================
org.quartz.scheduler.instanceName = TestScheduler1
org.quartz.scheduler.instanceId = AUTO
#==============================================================
#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
#==============================================================
#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.tablePrefix = QRTZ_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
一般我们的开发人员都喜欢使用
SPRING+QUARTZ
,因此这个
quartz.properties
都不用怎么去写,但是在集群方案中
quartz.properties
必写,如果不写
quartz
会调用自身
jar
包中的
quartz.properties
作为默认属性文件,同时修改
quartz.xml
文件。
Quartz.xml
文件的内容
:
<!-- 要调用的工作类 -->
<bean id="planOrderService" class="com.msd.store.order.service.impl.PlanQuartzOrders"></bean>
<bean id="planOrdertask" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.msd.store.commmons.MethodInvokingJobDetailFactoryBean</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="targetObject" value="planOrderService" />
<entry key="targetMethod" value="addwork" />
</map>
</property>
</bean>
<!-- 定义触发时间 -->
<bean id="planOrderDetail" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="planOrdertask" />
</property>
<!-- cron表达式 -->
<property name="cronExpression">
<value>0 0-5 23 * * ?</value>
</property>
</bean>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<bean id="mapScheduler" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource">
<ref bean="defaultSource"/>
</property>
<property name="triggers">
<list>
<ref bean="planOrderDetail" />
</list>
</property>
<property name="applicationContextSchedulerContextKey" value="applicationContext"/>
<property name="configLocation" value="classpath:quartz.properties"/>
</bean>
</beans>
分享到:
相关推荐
quartz在集群环境下的最终解决方案quartz在集群环境下的最终解决方案
需要把app部署在多台服务器上,但只能让其中一台服务器的job执行,一台服务器挂了,另一台还能继续执行job,通过网上查找资料,都是java工程的方式,不好部署并测试,经过二天辛苦整合,终于整理成一个单spring web...
java + quartz实现定时任务,实现集群配置,在集群环境下多节点运行定时Quartz定任务,就会存在重复处理任务的现象,为解决这一问题,下面我将介绍使用 Quartz 的 TASK ( 12 张表)实例化到数据库,基于数据库自动...
Autofac.Extras.Quartz, Quartz.Net的Autofac集成 Autofac.Extras.Quartz用于 Quartz.Net的Autofac集成包。Autofac.Extras.Quartz 为每个石英作业创建嵌套的litefime作用域。 完成作业执行后释放嵌套作用域。这允许...
自己弄了将近一天的成果。主要是修改MethodInvokingJobDetailFactoryBean这个类。
专业书 Spring Quatz 书-Quartz.Job.Scheduling.Framework.Building
quartz-2.4.0-SNAPSHOT-distribution.tar.gz包,解压后可查看里面的simple
NULL 博文链接:https://kissroom112.iteye.com/blog/2224442
spring4.0.6+quartz 2.2.3 集群示例
NULL 博文链接:https://vista-move.iteye.com/blog/2274246
Quartz在Spring中动态设置cronExpression.docx 相当不错的资料 小而全面
spring 集成quartz定时任务 用数据库实现quartz的集群
一个基于springboot的quartz集群dome。 向http://localhost:9090/job/addjob注入3个参数 类名:(及时定时任务的类如:com.ybjdw.site.job.NewJob) 组名:随意 定时启动方法:如“0/3 * * * * ?”(每3秒启动一次...
所需jar如下: spring-beans-3.2.4.RELEASE.jar spring-core-3.2.4.RELEASE.jar spring-expression-3.2.4.RELEASE....quartz-all-2.1.7.jar spring-tx-3.2.4.RELEASE.jar slf4j-log4j12-1.6.1.jar slf4j-api-1.6.1.jar
最近项目中使用了spring+Quartz定时任务、但是项目最近要集群部署、多个APP下如何利用Quartz 协调处理任务。 大家可以思考一下、现在有 A、B、C三个应用同时作为集群服务器对外统一提供服务、每个应用下各有一个...
NULL 博文链接:https://soulshard.iteye.com/blog/337886
SpringQuartz定时器的配置[参照].pdf
SpringQuartz定时器的配置[归类].pdf
Quartz集群配置[定义].pdf
本人花费多日时间,亲测有效。所需文件代码完整,只需导入常用开发IDE和mysql数据库即可正常使用。