`

Spring quartz在集群环境下解决方案 .

阅读更多

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在集群环境下的最终解决方案 #### 背景与挑战 随着系统复杂度的提高以及业务需求的变化,越来越多的应用程序需要支持高可用性和可扩展性。为了满足这些需求,通常会选择将应用程序部署在集群环境中。...

    Spring Quartz Job 集群 终极解决方案

    需要把app部署在多台服务器上,但只能让其中一台服务器的job执行,一台服务器挂了,另一台还能继续执行job,通过网上查找资料,都是java工程的方式,不好部署并测试,经过二天辛苦整合,终于整理成一个单spring web...

    完美解决多应用服务器负载均衡环境下spring quartz同一定时任务重复执行问题

    综上所述,解决Spring Quartz在负载均衡环境下的重复执行问题,需要综合运用Quartz的集群特性、数据库Job Store、公平调度以及应用层面的设计策略。通过这些方法,可以确保在多服务器环境中,定时任务的执行有序且...

    spring+quartz定时集群支持

    集群解决方案中,除了Spring+Quartz的配置,还可以采用统一调度Server来协调各个应用server的任务执行。例如,通过IHS(IBM HTTP Server)或者其他负载均衡器,可以实现对应用server的流量控制,确保同一时间只有一...

    quartz+spring分布式集群调度

    3. **监控和管理**: 实现对Quartz集群的监控,如任务状态、运行时性能等,以便及时发现和解决问题。 总结,Quartz+Spring的分布式集群调度方案能够帮助开发者构建稳定且可扩展的定时任务系统。通过合理配置和实践,...

    spring3+quartz1.6.4 集群示例

    本示例"spring3+quartz1.6.4 集群示例"是将两者结合,以实现一个能够支持集群的定时任务管理解决方案。 1. **Spring 3.x 框架** Spring 3.x 是Spring框架的一个版本,它引入了许多新特性,包括对Java 5和6的支持,...

    Spring集群整合Quartz

    本文将深入探讨如何在Spring集群环境中整合Quartz,实现高可用、可扩展的定时任务解决方案。 **1. Spring与Quartz的集成** Spring通过Spring Job和Spring Task模块提供了轻量级的任务调度能力,但当面临复杂定时...

    Spring Quartz1.8.x

    通过以上介绍,我们可以看到Spring Quartz 1.8.x为Java开发者提供了一个强大且灵活的任务调度解决方案,使得在Spring应用中实现定时任务变得简单易行。无论是简单的定时任务还是复杂的调度需求,都能在Spring Quartz...

    quartz整合springbatch定时集群实现mysql参考模版

    总的来说,"quartz_springbatch"模版提供了一个完整的解决方案,用于构建基于Quartz和SpringBatch的定时任务集群,且与MySQL数据库集成,确保数据的可靠性和任务的高可用性。通过学习和理解这个模版,开发者可以快速...

    Quartz集群+spring data

    至于博文链接中的内容,虽然无法直接查看,但通常会包含如何在实际项目中设置Quartz集群和Spring Data集成的详细步骤,包括配置示例、代码示例以及可能遇到的问题和解决方案。 在使用过程中,可能会遇到如任务并发...

    Spring+Quartz集群部署案例

    最近项目中使用了spring+Quartz定时任务、但是项目最近要... 解决方案一:只在一台 应用 上装 Quartz,其它两台不装,这样集群就没有意义了。 解决方案二:使用其实Quartz自身可以实例化数据库的特性就可以解决问题

    spring的quartz使用实例

    Spring整合Quartz是一款常见的任务调度解决方案,它允许开发者在应用程序中安排定时任务的执行。Quartz是一个开源的作业调度框架,而Spring通过提供一个简洁的API使得与Quartz的集成变得简单。以下是对Spring整合...

    定时框架spring+quartz

    "定时框架spring+quartz"的结合,就是将Quartz的定时功能与Spring的强大集成能力完美融合,为开发者提供了一种高效、灵活的定时任务解决方案。 Spring框架提供了多种方式来管理定时任务,包括使用Spring的`@...

    quartz集群 分布式

    综上所述,Spring Quartz结合Quartz集群提供了一种强大而灵活的分布式任务调度解决方案,能够有效地管理和执行定时任务,确保在多服务器环境下的高可用性和稳定性。在实际应用中,根据具体业务需求进行适当的优化和...

    spring java 定时器 执行两次 quartz

    总的来说,Spring集成Quartz提供了灵活的定时任务解决方案,但同时需要注意避免配置错误和并发问题,以防止任务被执行多次。通过理解Quartz的工作原理和Spring的定时任务API,我们可以有效地管理定时任务,确保它们...

    Spring的定时任务开发及对Quartz和Timer支持

    总的来说,Spring为定时任务提供了灵活且强大的解决方案,无论是使用自身的API还是集成第三方库如Quartz,都能满足各种复杂的需求。理解并熟练掌握这些知识,对于开发高效、稳定的后台服务至关重要。在实际项目中,...

    11-Spring+Quartz定时任务最简集群版1

    【Spring+Quartz定时任务最简集群版1】是一个基于Spring和Quartz的定时任务解决方案,用于在分布式环境中实现任务的自动调度。本项目作为Dubbo工程的一部分,它依赖于Dubbo的一些公共组件,同时也提供了将定时任务...

    Spring整合Quartz

    Spring整合Quartz是一个常见的任务调度解决方案,用于在Java应用程序中执行定时任务。Quartz是一个功能强大的、开放源代码的作业调度框架,而Spring框架则是一个全面的企业级应用开发框架。将两者结合,我们可以利用...

    Spring-quartz实现定时器(含代码)

    Spring是一个开源的Java平台,它提供了全面的企业级应用程序开发解决方案,包括依赖注入(DI)、面向切面编程(AOP)以及丰富的数据访问和事务管理功能。Spring的模块化设计使得开发者可以根据项目需求选择必要的...

    spring quartz 整合示例

    在IT行业中,Spring框架与Quartz的整合是一个常见的任务调度解决方案。这个压缩包文件提供了一个实际的示例,用于演示如何在Spring应用中集成Quartz进行任务调度。下面将详细解释其中涉及的知识点。 首先,Quartz是...

Global site tag (gtag.js) - Google Analytics