Spring quartz集群配置

starlin 1,092 2018-08-16

该篇文章主要是记录quartz在集群中的使用,以便后续不时之需,废话不多说,开始表演
用到的工具如下:

  • Quartz 2.2.3
  • Spring 4.3.4
  • Mysql 5.7

准备工作

  1. 下载
    下载地址:点我下载

  2. 建表
    将下载好的Quartz解压后找到\quartz-2.2.3\docs\dbTables目录,选择合适的sql语句,然后在MySql数据库中创建即可
    这里我选择的是tables_mysql_innodb.sql

quartz.properties的配置

配置如下:


#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
#调度器实例名称
org.quartz.scheduler.instanceName: testScheduler
#调度器实例编号自动生成
org.quartz.scheduler.instanceId: AUTO
org.quartz.scheduler.rmi.export:false
org.quartz.scheduler.rmi.proxy:false
org.quartz.scheduler.skipUpdateCheck: true

#============================================================================
# Configure ThreadPool  
#============================================================================
#线程池实现类
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
#执行最大并发线程数量
org.quartz.threadPool.threadCount: 10
#线程优先级
org.quartz.threadPool.threadPriority: 5
#是否自动加载任务,默认true自动加载数据库内的任务到节点
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true


#============================================================================
# Configure JobStore  
#============================================================================
org.quartz.jobStore.misfireThreshold: 60000
#Quartz中的Trigger和Job需要存储下来才使用,在Quartz中有两种存储方式,分别为RAMJobStore和JobStoreSupport
#其中RAMJobStore是将Trigger和Job存储在内存中,而后者存储在数据库中
#RAMJobStore存储的速度非常快,但由于系统停止后会丢失所有数据,一般在通常应用中使用后者
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
#持久化方式配置数据驱动,MySQL数据库
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#配置是否使用
org.quartz.jobStore.useProperties: true
#quartz相关数据表前缀名
org.quartz.jobStore.tablePrefix: QRTZ_
#该值如果为true,则表示开启集群模式
org.quartz.jobStore.isClustered: true
#分布式节点有效性检查时间间隔,单位:毫秒
org.quartz.jobStore.clusterCheckinInterval:5000

org.quartz.jobStore.txIsolationLevelReadCommitted:true


#============================================================================
# Configure Datasources  
# 因为spring xml文件中配置了数据库连接,所以就没有在此再次配置了
#============================================================================

#org.quartz.dataSource.myDS.driver: org.postgresql.Driver
#org.quartz.dataSource.myDS.URL: jdbc:postgresql://localhost/dev
#org.quartz.dataSource.myDS.user: jhouse
#org.quartz.dataSource.myDS.password: 
#org.quartz.dataSource.myDS.maxConnections: 5



#============================================================================
# Configure Plugins 
#============================================================================

org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames: quartz/spring-quartz.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound: true
org.quartz.plugin.jobInitializer.scanInterval: 120
org.quartz.plugin.jobInitializer.wrapInUserTransaction: false

spring-quartz.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:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
   ">

    <context:component-scan base-package="starlin.quartz.demo"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass">
            <value>com.mysql.jdbc.Driver</value>
        </property>
        <property name="jdbcUrl">
            <value>jdbc:mysql://localhost:3306/quartz?serverTimezone=GMT%2B8</value>
        </property>
        <property name="user">
            <value>root</value>
        </property>
        <property name="password">
            <value>root</value>
        </property>
    </bean>

    <!-- 配置线程池-->
    <!--<bean name="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">-->
        <!--<property name="corePoolSize" value="10"/>-->
        <!--<property name="maxPoolSize" value="20"/>-->
        <!--<property name="queueCapacity" value="100"/>-->
    <!--</bean>-->

    <!-- 自定义任务 -->
    <bean id="helloTask1" class="starlin.quartz.demo.HelloTask1"/>

    <bean id="firstTask" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="starlin.quartz.demo.HelloTask1"/>
        <!--<property name="name" value="doTask"/>-->
        <property name="durability" value="true"/>
        <!--requestsRecovery属性必须设置为 true,当Quartz服务被中止后,再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务。-->
        <property name="requestsRecovery" value="true" />
    </bean>

    <!--配置调度使用的触发器-->
    <!--提供了两种触发器类型:SimpleTriggerFactoryBean和CronTriggerFactoryBean-->
    <bean id="firstCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="firstTask"/>
        <!--<property name="startDelay" value="3000" />-->
        <!--<property name="repeatInterval" value="2000" />-->
        <property name="cronExpression" value="0 */1 * * * ?" />
    </bean>

    <!-- 配置调度任务-->
    <!-- 这里的id要和quartz.properties中的org.quartz.scheduler.instanceName保持一致-->
    <bean id="testScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="classpath:quartz/quartz.properties"/>
        <property name="dataSource" ref="dataSource"/>
        <!-- 设置自动启动 -->
        <property name="autoStartup" value="true" />
        <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
        <property name="triggers">
            <list>
                <ref bean="firstCronTrigger"/>
            </list>
        </property>
    </bean>
</beans>

创建定时任务类

HelloTask1类

public class HelloTask1 implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Hello World! MyJob is executing.11");
    }
}    

创建测试类

App类

public class App {
    public static void main(String[] args) {
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("quartz/spring-quartz.xml");
    }
}

测试

测试步骤如下:

  1. 为了达到集群效果,需要将同样的代码copy一份,然后启动两个main方法
  2. 测试结果显示,根据设定的定时任务时间,有且仅有一台能够正常执行,其中一台停止服务后,另外一台依然能够正常运行

结语:虽然Quartz能够满足分布式定时任务的需要,但还是推荐Elastic-Job,后续再来介绍


# quartz