6quartz在集群环境下的最终解决方案.docx

上传人:b****6 文档编号:12590782 上传时间:2023-06-06 格式:DOCX 页数:9 大小:18.31KB
下载 相关 举报
6quartz在集群环境下的最终解决方案.docx_第1页
第1页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第2页
第2页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第3页
第3页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第4页
第4页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第5页
第5页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第6页
第6页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第7页
第7页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第8页
第8页 / 共9页
6quartz在集群环境下的最终解决方案.docx_第9页
第9页 / 共9页
亲,该文档总共9页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

6quartz在集群环境下的最终解决方案.docx

《6quartz在集群环境下的最终解决方案.docx》由会员分享,可在线阅读,更多相关《6quartz在集群环境下的最终解决方案.docx(9页珍藏版)》请在冰点文库上搜索。

6quartz在集群环境下的最终解决方案.docx

6quartz在集群环境下的最终解决方案

在集群环境下,大家会碰到一直困扰的问题,即多个 APP 下如何用 quartz 协调处理自动化 JOB 。

大家想象一下,现在有 A , B , C3 台机器同时作为集群服务器对外统一提供 SERVICE :

A , B , C3 台机器上各有一个 QUARTZ ,他们会按照即定的 SCHEDULE 自动执行各自的任务。

我们先不说实现什么功能,就说这样的架构其实有点像多线程。

那多线程里就会存在“资源竞争”的问题,即可能产生脏读,脏写,由于三台 APPSERVER 里都有QUARTZ ,因此会存在重复处理 TASK 的现象。

一般外面的解决方案是只在一台 APP 上装 QUARTZ ,其它两台不装,这样集群就形同虚设了;

另一种解决方案是动代码,这样就要影响到原来已经写好的 QUARTZJOB 的代码了,这对程序开发人员来说比较痛苦;

本人仔细看了一下 Spring 的结构和 QUARTZ 的文档,结合 Quartz 自身可以实例化进数据的特性找到了相关的解决方案。

本方案优点:

1.       每台作为集群点的 APPSERVER 上都可以布署 QUARTZ ;

2.       QUARTZ 的 TASK ( 12 张表)实例化如数据库,基于数据库引擎及 High-Available 的策略(集群的一种策略)自动协调每个节点的 QUARTZ ,当任一一节点的 QUARTZ 非正常关闭或出错时,另几个节点的 QUARTZ 会自动启动;

3.       无需开发人员更改原已经实现的 QUARTZ ,使用 SPRING+ 类反射的机制对原有程序作切面重构;

本人也事先搜索了一些资料,发觉所有目前在 GOOGLE 上或者在各大论坛里提供的解决方案,要么是只解决了一部分,要么是错误的,要么是版本太老,要么就是完全抄别人的。

尤其是在使用 QUARTZ+SPRING 对数据库对象作实例化时会抛错(源于 SPRING 的一个 BUG ),目前网上的解决方案全部是错的或者干脆没说,本人在此方案中也会提出如何解决。

解决方案:

 

1.       把 QUARTZ 的 TASK 实例化进数据库, QUARTZ 只有实例化进入数据库后才能做集群,外面的解决方案说实例化在内存里全部是错的,把quartz-1.8.4/docs/dbTables/tables_oracle.sql 在 ORACLE9I2 及以上版本中执行一下会生成 12 张表;

2.       生成 quartz.properties 文件,把它放在工程的 src 目录下,使其能够被编译时纳入 classpath 。

一般我们的开发人员都喜欢使用 SPRING+QUARTZ ,因此这个 quartz.properties 都不用怎么去写,但是在集群方案中 quartz.properties 必写,如果不写 quartz 会调用自身 jar 包中的 quartz.properties 作为默认属性文件,同时修改 quartz.xml 文件。

 

Quartz.xml 文件的内容 :

 

xmlversion="1.0"encoding="UTF-8"?

>

DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:

//www.springframework.org/dtd/spring-beans.dtd ">

               

                               class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

                                

quartz.properties"/>

                               

                                               

                                                               

                                               

                               

                               

— 就是下面这句,因为该 bean 只能使用类反射来重构

                                          

 

quartz.properties 文件的内容:

 

org.quartz.scheduler.instanceName=mapScheduler 

org.quartz.scheduler.instanceId=AUTO 

 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX 

 org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate 

 org.quartz.jobStore.dataSource=myXADS 

 org.quartz.jobStore.tablePrefix=QRTZ_ 

 org.quartz.jobStore.isClustered=true 

  

 org.quartz.dataSource.myXADS.jndiURL=jdbc/TestQuartzDS

 org.quartz.dataSource.myXADS.jndiAlwaysLookup=DB_JNDI_ALWAYS_LOOKUP 

 org.quartz.dataSource.myXADS.java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory 

 org.quartz.dataSource.myXADS.java.naming.provider.url=t3:

//localhost:

7020 

 org.quartz.dataSource.myXADS.java.naming.security.principal=weblogic 

 org.quartz.dataSource.myXADS.java.naming.security.credentials=weblogic 

3.       重写 quartz 的 QuartzJobBean 类

原因是在使用 quartz+spring 把 quartz 的 task 实例化进入数据库时,会产生:

 serializable 的错误,原因在于:

                               

                                               

                               

                               

                                               execute

                               

这个 MethodInvokingJobDetailFactoryBean 类中的 methodInvoking 方法,是不支持序列化的,因此在把QUARTZ 的 TASK 序列化进入数据库时就会抛错。

网上有说把 SPRING 源码拿来,修改一下这个方案,然后再打包成 SPRING.jar 发布,这些都是不好的方法,是不安全的。

必须根据 QuartzJobBean 来重写一个自己的类,然后使用 SPRING 把这个重写的类(我们就名命它为:

MyDetailQuartzJobBean )注入 appContext 中后,再使用 AOP 技术反射出原有的 quartzJobx( 就是开发人员原来已经做好的用于执行 QUARTZ 的 JOB 的执行类 ) 。

下面来看 MyDetailQuartzJobBean 类:

 

publicclassMyDetailQuartzJobBeanextendsQuartzJobBean{

               protectedfinalLoglogger=LogFactory.getLog(getClass());

 

               privateStringtargetObject;

               privateStringtargetMethod;

               privateApplicationContextctx;

 

               protectedvoidexecuteInternal(JobExecutionContextcontext)

                                               throwsJobExecutionException{

                               try{

 

                                               logger.info("execute["+targetObject+"]atonce>>>>>>");

                                               ObjectotargetObject=ctx.getBean(targetObject);

                                               Methodm=null;

                                               try{

                                                               m=otargetObject.getClass().getMethod(targetMethod,

                                                                                               newClass[]{});

 

                                                               m.invoke(otargetObject,newObject[]{});

                                               }catch(SecurityExceptione){

                                                               logger.error(e);

                                               }catch(NoSuchMethodExceptione){

                                                               logger.error(e);

                                               }

 

                               }catch(Exceptione){

                                               thrownewJobExecutionException(e);

                               }

 

               }

 

               publicvoidsetApplicationContext(ApplicationContextapplicationContext){

                               this.ctx=applicationContext;

               }

 

               publicvoidsetTargetObject(StringtargetObject){

                               this.targetObject=targetObject;

               }

 

               publicvoidsetTargetMethod(StringtargetMethod){

                               this.targetMethod=targetMethod;

               }

 

}

再来看完整的 quartz.xml (注意红色加粗部分尤为重要):

xmlversion="1.0"encoding="UTF-8"?

>

DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:

//www.springframework.org/dtd/spring-beans.dtd ">

               

                               class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

                                

quartz.properties"/>

                               

                                               

                                                               

                                               

                               

                               

                               

               

               

 

 

               

               

 

                

                               

                                               com.testcompany.framework.quartz. MyDetailQuartzJobBean 

                               

                               

                                               

                                                               

                                                               

                                               

                               

               

 

               

                               

                                               

                               

                               

                                               0/5****?

                               

               

4.       下载最新的 quartz1.8 版,把 quartz-all-1.8.4.jar,quartz-oracle-1.8.4.jar,quartz-weblogic-1.8.4.jar 这三个包放到 web-inf/lib 目录下,布署。

   

测试:

 

几个节点都带有 quartz 任务,此时只有一台 quartz 在运行,另几个节点上的 quartz 没有运行。

 

此时手动 shutdown 那台运行 QUARTZ (在程序里加 system.out.println(“executeonce…”), 运行 quartz的那个节点在后台会打印 executeonce )的节点,过了 7 秒左右,另一个节点的 quartz 自动监测到了集群中运行着的 quartz 的 instance 已经 shutdown ,因此 quartz 集群会自动把任一台可用的 APP 上启动起一个 quartzjob 的任务。

 

自此, QUARTZ 使用 HA 策略的集群大功告成,不用改原有代码,配置一下我们就可作到 QUARTZ 的集群与自动错误冗余。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2