共同执行同一个Qu ar tz任务列表,多台服务器同时执行任务,生成业务数据文件。不知道有人做过没有啊。希望得到大家的帮助啊?或者提供点资料?思路?

解决方案 »

  1.   

    虽然单个Quartz实例能给予你很好的Job调度能力,但它不能满足典型的企业需求,如可伸缩性、高可靠性满足。假如你需要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部分了。使用 Quartz 的集群能力可以更好的支持你的业务需求,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的 Job 得到执行。 Quartz 中集群如何工作 一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。 创建Quartz数据库表 因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。Quartz 包括了所有被支持的数据库平台的 SQL 脚本。在 <quartz_home>/docs/dbTables 目录下找到那些 SQL 脚本,这里的 <quartz_home> 是解压 Quartz 分发包后的目录。 
    这里采用的Quartz 1.6.5版本,总共12张表,不同版本,表个数可能不同。数据库为mysql,用tables_mysql_innodb.sql创建数据库表。 配置数据库连接池 1.配置jdbc.properties文件 引用jdbc.driverClassName=com.mysql.jdbc.Driver 
    jdbc.url=jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true 
    jdbc.username=root 
    jdbc.password=kfs 2.配置applicationContext.xml文件 引用<?xml version="1.0" encoding="UTF-8"?> 
    <beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:context="http://www.springframework.org/schema/context" 
         xmlns:jee="http://www.springframework.org/schema/jee" 
        xsi:schemaLocation=" 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
         http://www.springframework.org/schema/jee 
           http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"  > 
      
       <context:component-scan base-package="com.sundoctor"/> <!-- 属性文件读入 --> 
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="locations"> 
    <list> 
    <value>classpath:jdbc.properties</value> 
    </list> 
    </property> 
    </bean> <!-- 数据源定义,使用c3p0 连接池 --> 
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
    <property name="driverClass" value="${jdbc.driverClassName}" /> 
    <property name="jdbcUrl" value="${jdbc.url}" /> 
    <property name="user" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
    <property name="initialPoolSize" value="5" /> 
    <property name="minPoolSize" value="5" /> 
    <property name="maxPoolSize" value="20" /> 
    <property name="acquireIncrement" value="2" /> 
    <property name="maxIdleTime" value="3600" /> 
    <property name="idleConnectionTestPeriod"  value="180"/>  
    <property name="automaticTestTable" value="C3P0TESTTABLE"/> 
    </bean> 
    </beans> 创建Job测试服务类 Java代码 
    package com.sundoctor.quartz.cluster.example;   
      
    import java.io.Serializable;   
      
    import org.slf4j.Logger;   
    import org.slf4j.LoggerFactory;   
    import org.springframework.stereotype.Service;   
      
    @Service("simpleService")   
    public class SimpleService implements Serializable{   
           
        private static final long serialVersionUID = 122323233244334343L;   
        private static final Logger logger = LoggerFactory.getLogger(SimpleService.class);   
           
        public void testMethod1(){   
            //这里执行定时调度业务   
            logger.info("testMethod1.......1");   
        }   
           
        public void testMethod2(){   
            logger.info("testMethod2.......2");    
        }   
    }  package com.sundoctor.quartz.cluster.example;import java.io.Serializable;import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Service;@Service("simpleService")
    public class SimpleService implements Serializable{

    private static final long serialVersionUID = 122323233244334343L;
    private static final Logger logger = LoggerFactory.getLogger(SimpleService.class);

    public void testMethod1(){
    //这里执行定时调度业务
    logger.info("testMethod1.......1");
    }

    public void testMethod2(){
    logger.info("testMethod2.......2");
    }
    }
    因为Job需要持久化到数据库中,SimpleService必须实现Serializable接口,在这里只是简单打印一下日志。 配置 Quartz 使用集群 
      

  2.   

    1.配置节点的 quartz.properties 文件 引用org.quartz.scheduler.instanceName = TestScheduler1   
    org.quartz.scheduler.instanceId = AUTO  org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 
    org.quartz.threadPool.threadCount = 10 
    org.quartz.threadPool.threadPriority = 5 
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true 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 
    org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。 org.quartz.scheduler.instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID。 org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。 org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。 org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。 2.配置applicationContext-quartz.xml文件 引用<?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> 
        <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
            <property name="dataSource"> 
                <ref bean="dataSource"/> 
            </property> 
            <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/> 
            <property name="configLocation" value="classpath:quartz.properties"/> 
    <property name="triggers"> 
    <list>   
    <ref bean="trigger1"/> 
    <ref bean="trigger2"/> 
    </list> 
    </property> 
        </bean> 
        
        <bean id="jobDetail1" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> 
            <property name="targetObject" ref="simpleService"/> 
            <property name="targetMethod" value="testMethod1"/> 
    <property name="shouldRecover" value="true"/> 
        </bean> 
        <bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerBean"> 
            <property name="jobDetail" ref="jobDetail1"/> 
            <property name="cronExpression" value="0/5 * * ? * * *"/> 
        </bean>    
      
        <bean id="jobDetail2" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> 
            <property name="targetObject" ref="simpleService"/> 
            <property name="targetMethod" value="testMethod2"/> 
    <property name="shouldRecover" value="true"/> 
        </bean> 
        <bean id="trigger2" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> 
            <property name="jobDetail" ref="jobDetail2"/> 
            <property name="startDelay" value="1"/> 
            <property name="repeatCount" value="100"/> 
            <property name="repeatInterval" value="1000"/> 
        </bean>    
    </beans> dataSource:项目中用到的数据源,里面包含了quartz用到的12张数据库表; applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所 定义的key得到对应的spring上下文; configLocation:用于指明quartz的配置文件的位置 关于Job配置,这里有两点需要注意 
    MethodInvokingJobDetailFactoryBean 
    在这里使用牛人修改后的frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean,可以参考: http://jira.springframework.org/browse/SPR-3797。直接使用org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean会报java.io.NotSerializableException异常。 shouldRecover 
    shouldRecover属性必须设置为 true,当Quartz服务被中止后,再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务。 运行Quartz集群 在相同或不同的机器上运行com.sundoctor.quartz.cluster.example.test.MainTest进行测试,在本例中只是简单打印一下日志。 
    Java代码 
    package com.sundoctor.quartz.cluster.example.test;   
      
    import org.springframework.context.ApplicationContext;   
    import org.springframework.context.support.ClassPathXmlApplicationContext;   
      
    public class MainTest {   
      
        /**  
         * @param args  
         */  
        public static void main(String[] args) {   
            ApplicationContext springContext = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext.xml","classpath:applicationContext-quartz.xml"});   
        }   
      
    }  package com.sundoctor.quartz.cluster.example.test;import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest { /**
     * @param args
     */
    public static void main(String[] args) {
    ApplicationContext springContext = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext.xml","classpath:applicationContext-quartz.xml"});
    }}
    Quartz 实际并不关心你是在相同的还是不同的机器上运行节点。当集群是放置在不同的机器上时,通常称之为水平集群。节点是跑在同一台机器是,称之为垂直集群。对于垂直集群,存在着单点故障的问题。这对高可用性的应用来说是个坏消息,因为一旦机器崩溃了,所有的节点也就被有效的终止了。 当你运行水平集群时,时钟应当要同步,以免出现离奇且不可预知的行为。假如时钟没能够同步,Scheduler 实例将对其他节点的状态产生混乱。有几种简单的方法来保证时钟何持同步,而且也没有理由不这么做。最简单的同步计算机时钟的方式是使用某一个 Internet 时间服务器(Internet Time Server ITS)。 没什么会阻止你在相同环境中使用集群的和非集群的 Quartz 应用。唯一要注意的是这两个环境不要混用在相同的数据库表。意思是非集群环境不要使用与集群应用相同的一套数据库表;否则将得到希奇古怪的结果,集群和非集群的 Job 都会遇到问题。 假如你让一个非集群的 Quartz 应用与集群节点并行着运行,设法使用 JobInitializationPlugin和 RAMJobStore。 每个Quartz节点都是直接与数据库通信,并不与任何其它的节点通信。需要所有节点服务器时钟同步,所有节点共享一套数据库表,每个节点是通过数据库表记录的时间来知道当前那些Trigger在执行。 
      

  3.   

    quart 不支持集群 也没有集群的概念,使用quartz的应用都没有办法做群集。 如果是我的话,我采取的办法就是自己单独启动一个Job Server,来跑job,不会部署在web容器中。 其他web节点当需要启动异步任务的时候,可以通过种种方式(DB, JMS, Web Service, etc)通知Job Server,而Job Server收到这个通知之后,把异步任务加载到自己的任务队列中去。 
      

  4.   

    一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。  
      

  5.   

    我粗略查了下,貌似也是支持的,你可以贴下你看的资料嘛
    http://www.quartz-scheduler.org/docs/configuration/ConfigJDBCJobStoreClustering.html
    你指的同时执行任务是同一个任务吗?
      

  6.   

    http://www.javabeat.net/qna/156-clustering-in-quartz-scheduler/
    这里有讲Clustering in quartz Scheduler
    不过局限于JDBC-Jobstore (JobStoreTX or JobStoreCMT) 不知是不是最新支持功能列表,如有扩展了就好了
      

  7.   

    这个  我觉的spring框架quartz支持集群
      

  8.   


    Quartz不支持集群吗? 我们做的应用貌似就用Quartz集群了哎,实际上Quartz集群靠的是数据库,设置每个任务的状态(运行/完成/等待...)