zoukankan      html  css  js  c++  java
  • (4) Spring中定时任务Quartz集群配置学习

    原 来配置的Quartz是通过spring配置文件生效的,发现在非集群式的服务器上运行良好,但是将工程部署到水平集群服务器上去后改定时功能不能正常运 行,没有任何错误日志,于是从jar包、JDK版本、cronExpression到服务器类型,甚至查到了服务器操作系统的类型,都没能找到解决的办 法,后来才知道是集群惹的祸!

    详细步骤如下:

    1、 按照Quartz集群工作原理

    图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知

    在数据库中建表。建表模版在Quartz包下docs/dbTables下,选择相应的数据库和版本即可。ORACLE的11个Table列表如下:

    QRTZ_JOB_LISTENERS:存储有关已配置的 JobListener 的信息

    •  JOB_NAME
    •  JOB_GROUP
    •  JOB_LISTENER

    QRTZ_TRIGGER_LISTENERS:存储已配置的 TriggerListener 的信息

    QRTZ_FIRED_TRIGGERS:存储与已触发的 Trigger 相关的状态信息,以及相联 Job的执行信息

    QRTZ_PAUSED_TRIGGER_GRPS:存储已暂停的 Trigger 组的信息

    QRTZ_SCHEDULER_STATE:存储集群中note实例信息,quartz会定时读取该表的信息判断集群中每个实例的当前状态

    •  INSTANCE_NAME 之前配置文件中org.quartz.scheduler.instanceId配置的名字,就会写入该字段,如果设置为AUTO,quartz会根据物理机名和当前时间产生一个名字
    •  LAST_CHECKIN_TIME:上次检查时间
    •  CHECKIN_INTERVAL :检查间隔时间

    QRTZ_LOCKS:存储程序的悲观锁的信息(假如使用了悲观锁

    QRTZ_SIMPLE_TRIGGERS:存储简单的Trigger,包括重复次数,间隔,以及已触的次数

    •  TRIGGER_NAME :qrtz_triggerstrigger_name的外键
    •  TRIGGER_GROUP:qrtz_triggerstrigger_group的外键
    •  REPEAT_COUNT :重复次数
    •  REPEAT_INTERVAL:时间间隔
    •  TIMES_TRIGGERED:触发次数

    QRTZ_CRON_TRIGGERS:存储cron表达式表

    •  TRIGGER_NAME :qrtz_triggerstrigger_name的外键
    •  TRIGGER_GROUP:qrtz_triggerstrigger_group的外键 
    •  CRON_EXPRESSION:cron表达式
    •  TIME_ZONE_ID :时区

    QRTZ_TRIGGERS:保存trigger信息

    •  TRIGGER_NAME :trigger的名字,该名字用户自己可以随意定制,无强行要求
    •  TRIGGER_GROUP:所属组的名字,该名字用户自己随意定制,无强行要求
    •  JOB_NAME :qrtz_job_detailsjob_name的外键
    •  JOB_GROUP :qrtz_job_detailsjob_group的外键
    •  IS_VOLATILE 0
    •  DESCRIPTION
    •  NEXT_FIRE_TIME
    •  PREV_FIRE_TIME
    •  PRIORITY 5
    •  TRIGGER_STATE :当前trigger状态,设置为ACQUIRED,如果设置为WAITING,job不会触发
    •  TRIGGER_TYPE:触发器类型,使用cron表达式
    •  START_TIME
    •  END_TIME
    •  CALENDAR_NAME
    •  MISFIRE_INSTR
    •  JOB_DATA

    QRTZ_JOB_DETAILS:保存job详细信息,该表需要用户根据实际情况初始化

    •  JOB_NAME :集群中job的名字,该名字用户自己可以随意定制,无强行要求
    •  JOB_GROUP :集群中job的所属组的名字,该名字用户自己随意定制,无强行要求 
    •  DESCRIPTION
    •  JOB_CLASS_NAME:集群中个note job实现类的完全包名,quartz就是根据这个路径到classpath找到该job类 
    •  IS_DURABLE:是否持久化,把该属性设置为1quartz会把job持久化到数据库中
    •  IS_VOLATILE
    •  IS_STATEFUL
    •  REQUESTS_RECOVERY
    •  JOB_DATA :一个blob字段,存放持久化job对象

    QRTZ_CALENDARS:以 Blob 类型存储 Quartz 的 Calendar 信息

    QRTZ_BLOB_TRIGGERS:作为 Blob 类型存储(用于 Quartz 用户用 JDBC创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候

    •  TRIGGER_NAME :qrtz_triggerstrigger_name的外键
    •  TRIGGER_GROUP:qrtz_triggerstrigger_group的外键 
    •  BLOB_DATA

    2、 配置数据库连接池,如果spring已经配置则不需要再另行配置,只需在后面配置的applicationContext-quartz.xml引入即可。

    applicationContext.xml:

    <bean id="propertyConfigurer" 

    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 

    <property name="location"> 

    <value>classpath:dataConfig.properties</value> 

    </property> 

    </bean> 

     <bean id="ds34" class="org.apache.commons.dbcp.BasicDataSource" 

     destroy-method="close"> 

     <property name="driverClassName"> 

     <value>${ds34.driver}</value> 

     </property> 

     <property name="url"> 

     <value>${ds34.url}</value> 

     </property> 

     <property name="username"> 

     <value>${ds34.username}</value> 

     </property> 

     <property name="password"> 

     <value>${ds34.password}</value> 

     </property> 

     <property name="maxActive" value="5"></property> 

     <property name="maxIdle" value="20"></property> 

     <property name="maxWait" value="50"></property> 

     <property name="defaultAutoCommit" value="true"></property> 

    </bean>

    dataConfig.properties:

    jdbc.driverClassName=oracle.jdbc.driver.OracleDriver

    jdbc.url=jdbc:oracle:thin:@localhost:1521:test

    jdbc.username=test

    jdbc.password=test

    3、 配置quartz.properties

    v org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。

    v org.quartz.scheduler.instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID

    v org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore

    v org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。

    v org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (15 )

    quartz.properties:

    ##Quartz 调度任务所需的配置文件 

    ##org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。 

    org.quartz.scheduler.instanceName = HumsScheduler 

    ##org.quartz.scheduler.instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID。 

    org.quartz.scheduler.instanceId = AUTO 

    orgorg.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属性为 JobStoreTX,将任务持久化到数据中。 

    ##因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。 

    ##这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。 

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

    orgorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate 

    org.quartz.jobStore.tablePrefix = QRTZ_ 

    org.quartz.jobStore.maxMisfiresToHandleAtATime=10 

    ##org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。 

    ##这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。 

    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

    4、 配置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/1 * ? * * *"/>

        </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>

    5、 配置Job任务注意:加入定时任务有两种方式:

    ① 继承QuartzJobBean的类,重写executeInternal(),详细写法:

    <bean id="jobDetail1" class="org.springframework.scheduling.quartz.JobDetailBean">
     <property name="jobClass">
     <value>继承QuartzJobBean的类的引用</value>
     </property>
    </bean>

    ② 用 org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean 指定类和方法,但是直接使用会报java.io.NotSerializableException异常,一般用网上流传的(需要将两个类copy到自己 的工程下,要有springJAR包,Job需要持久化到数据库中,SimpleService必须实现 Serializable)frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean。 详细写法:

    <bean id="jobDetail1" class=" 工程里MethodInvokingJobDetailFactoryBean的路径.MethodInvokingJobDetailFactoryBean"> 

    <property name="targetObject" ref="simpleService"/> 

    <property name="targetMethod" value="testMethod1"/> 

    <property name="shouldRecover" value="true"/> 

    </bean>

    6、 配置到spring配置文件,自动调度任务。

    <import resource="applicationContext-quartz.xml"></import>

    7、 测试用例

    public class MainTest {

    /**

     * @param args

     */

    public static void main(String[] args) {

    ApplicationContext springContext = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext.xml"});

    }

    }

  • 相关阅读:
    Java安全之对称加密、非对称加密、数字签名
    Java 设计模式 之 中介者模式(Mediator)
    使用jquery获取radio的值
    java6枚举类型
    java http头信息
    怎样用java生成GUID与UUID
    struts2国际化
    JSON.stringify(),JSON.parse(),toJSON()方法使用
    阻塞队列之六:LinkedBlockingDeque
    jQuery给控件赋值....
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/4508129.html
Copyright © 2011-2022 走看看