zoukankan      html  css  js  c++  java
  • 分布式任务调度——quartz + spring + 数据库

        项目中使用分布式并发部署定时任务,多台跨JVM,按照常理逻辑每个JVM的定时任务会各自运行,这样就会存在问题,多台分布式JVM机器的应用服务同时干活,一个是加重服务负担,另外一个是存在严重的逻辑问题,比如需要回滚的数据,就回滚了多次,刚好quartz提供很好的解决方案。
        集群分布式并发环境中使用QUARTZ定时任务调度,会在各个节点会上报任务,存到数据库中,执行时会从数据库中取出触发器来执行,如果触发器的名称和执行时间相同,则只有一个节点去执行此任务。 
        如果此节点执行失败,则此任务则会被分派到另一节点执行,中途也会自动检查失效的定时调度,发现不成功的,其他节点立马接过来继续完成定时任务。对应的定时任务调度表比较多,有11个。
     
    后续功能
        准备code一个web调度工作台,对所有job进行统计管理和监控;
     
    引入依赖:
    <!-- quartz -->
    <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
    </dependency>
     
    配置quartz数据库
        官网下载,tz压缩包,在解压目录docsdbTables下找到对应的执行sql,执行即可;
     
    配置本地quartz.properties
        单机版,使用RAMJobStore存储任务,可以使用jar包总默认配置,改方式执行最迅速,强大,方便;
        集群版本,需要copy出jar包中配置,新增如下配置,并注释掉重复配置项目,即可;
            # for cluster
            org.quartz.scheduler.instanceId: AUTO
            org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
            org.quartz.jobStore.isClustered: true
            org.quartz.jobStore.clusterCheckinInterval: 1000
     
    创建CronTrigger和JobDetail,二者为包含关系
    Quartz2.0创建JobDetail有两种方式:
    方式一:CronTrigger包含JobDetail,JobDetail用MethodInvokingJobDetailFactoryBean工厂Bean包装普通的Java对象或bean;
    <!-- Job trigger -->
    <bean id="job01Trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
          <property name="jobDetail" >
               <bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                    <property name="targetObject" ref="jobService" />
                    <property name="targetMethod" value="job01" />
                    <property name="concurrent" value="false" />
               </bean>
          </property>
          <property name="cronExpression" value="0/3 * * * * ? *" />
     </bean>
    方式二:CronTrigger包含JobDetail,JobDetail用JobDetailFactoryBean包装QuartzJobBean的继承子类(即Job类)的实例;
        <!-- Job trigger -->
        <bean id="job02Trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" >
                <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
                    <property name="jobClass" value="com.xxl.job.JobDetailDemo"/>
                    <property name="jobDataAsMap">
                        <map>
                            <!-- <entry key="xxService" value-ref="xxService" /> -->
                        </map>
                    </property>  
                    <property name="durability" value="true"></property>
                </bean>
            </property>
            <property name="cronExpression" value="0/1 * * * * ? *" />
        </bean>
     
    创建调度工厂,根据数据存储方式,分为两种
    方式一:内存RAMJobStore:把job的相关信息存储在内存里,如果用spring配置quartz的job信息的话,所有信息是配置在xml里,当spirng context启动的时候就把xml里的job信息装入内存。
    <bean name="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
          <property name="triggers">
               <list>
                    <ref bean="job01Trigger" />
               </list>
          </property>
     </bean>
    方式二:数据库:读取配置在数据库里的job初始化信息,并且把job通过java序列化到数据库里,这样就使得每个job信息得到了持久化,即使在jvm或者容器挂掉的情况下,也能通过数据库感知到其他job的状态和信息;quartz集群各节点之间是通过同一个数据库实例(准确的说是同一个数据库实例的同一套表)来感知彼此的。 
    <bean id="quartzScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
          <property name="dataSource" ref="dataSource" />
          <property name="autoStartup" value="true" />
          <property name="applicationContextSchedulerContextKey"  value="applicationContextKey" />
           <property name="configLocation" value="classpath:quartz.properties"/>
          <property name="triggers">
               <list>
                    <ref bean="job02Trigger" />
               </list>
          </property>
     </bean>
     
    tips:applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文。
     
    实例应用
    ..quartz-demo.zip..
     
     
     
     
     
  • 相关阅读:
    Solved:Spring Junit Test NoSuchMethodError
    Stack实现
    CLRS10.2-8练习
    CLRS10.2-7练习
    CLRS10.2-4练习
    CLRS10.1-7练习
    CLRS10.1-6练习
    算法:吸血鬼数字算法
    CLRS最大子数组问题
    VS快捷键
  • 原文地址:https://www.cnblogs.com/xuxueli/p/4866449.html
Copyright © 2011-2022 走看看