四、Quartz-集群实现

一、编码方式实现(无Spring)

1.配置文件编写
#==============================================================
#Configure Main Scheduler Properties
#==============================================================
org.quartz.scheduler.instanceName = quartzScheduler
org.quartz.scheduler.instanceId = AUTO

#==============================================================
#Configure JobStore
#==============================================================
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.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 10000  
org.quartz.jobStore.dataSource = myDS

#==============================================================
#Configure DataSource
#==============================================================
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://127.0.0.1:3306/quartz?useUnicode=true&characterEncoding=UTF-8
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = root
org.quartz.dataSource.myDS.maxConnections = 30

#==============================================================
#Configure ThreadPool
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
2.创建任务类
@PersistJobDataAfterExecution
public class MyJob implements Job {
    private static Logger logger = LoggerFactory.getLogger(MyJob.class);

    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail jobDetail = context.getJobDetail();
        //获取任务名字和任务组名
        JobKey key = jobDetail.getKey();
        logger.info("Job name and group:" + key);
        //打印当前时间
        logger.info("time:" + new Date());
        //获取执行次数,每次递增
        Integer count = (Integer) jobDetail.getJobDataMap().get("count");
        count = count + 1;
        jobDetail.getJobDataMap().put("count", count);
        logger.info("Job count :" + count +"....................");
    }
}
3.创建集群工具类
public class ClusterQuartzUtil {
    private static Logger logger = LoggerFactory.getLogger(ClusterQuartzUtil.class);

    /**
     * 创建触发器
     */
    public static Trigger createTrigger(String triggerName, String triggerGroup, String cronExpresion) {
        return newTrigger()
                .withIdentity(triggerName, triggerGroup)
                .withSchedule(cronSchedule(cronExpresion)
                    .inTimeZone(TimeZone.getTimeZone("Asia/Shanghai")))
                .build();
    }

    /**
     * 创建任务详情
     */
    public static JobDetail createJobDetail(String jobName, String jobGroup, Class clazz) {
        return JobBuilder
                .newJob(clazz)
                .withIdentity(jobName, jobGroup)
                .usingJobData("count", 0)
                //requestsRecovery属性必须设置为 true,当Quartz服务被中止后,再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务
                //尝试了一下。。不设置时默认为true
                .requestRecovery(true)
                .build();
    }

    /**
     * 创建调度器
     */
    public static Scheduler createScheduler() {
        StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = null;
        try {
            scheduler = stdSchedulerFactory.getScheduler();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return scheduler;
    }

}
4.主任务中进行测试
public class Sustainable {
    public static void main(String[] args) {
        JobDetail jobDetail = ClusterQuartzUtil.createJobDetail("job_1", "job_group_1", MyJob.class);
        Trigger trigger = ClusterQuartzUtil.createTrigger("trrigger_ 1", "trigger_group_1", "5/5 * * * * ?");
        Scheduler scheduler = ClusterQuartzUtil.createScheduler();
        try {
            if (!scheduler.checkExists(jobDetail.getKey())) {
                scheduler.scheduleJob(jobDetail, trigger);
            }
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

跑起主任务之后停掉再开,会发现计数记录扔保留,代表持久化起作用了
image
然后,尝试开启两个同样项目,当关闭其中一个时候,另外一个会接手执行任务,集群完成!

二、Spring + Quartz 实现集群

1.编写quartz配置文件
#==============================================================
#Configure Main Scheduler Properties 基础配置
#==============================================================
org.quartz.scheduler.instanceName = quartzScheduler
org.quartz.scheduler.instanceId = AUTO

#==============================================================
#Configure JobStore 存储机制配置
#==============================================================
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.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 10000  
org.quartz.jobStore.dataSource = myDS

#==============================================================
#Configure DataSource 数据源设置
#==============================================================
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://127.0.0.1:3306/quartz?useUnicode=true&characterEncoding=UTF-8
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = root
org.quartz.dataSource.myDS.maxConnections = 30

#==============================================================
#Configure ThreadPool 线程池设置
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
2.编写任务类
/**状态数据持久化
 * @author CaiShunfeng
 * @PersistJobDataAfterExecution: 数据持久化
 * @DisallowConcurrentExecution:  不可并发执行
 * */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class SpringClusterQuartzJob implements Job {
    private static Logger logger = LoggerFactory.getLogger(SpringClusterQuartzJob.class);

    public void execute(JobExecutionContext context) throws JobExecutionException {
        logger.info("do job for spring cluster");
        Integer count = (Integer) context.getJobDetail().getJobDataMap().get("count");
        logger.info("job count :" + count);
        context.getJobDetail().getJobDataMap().put("count", count + 1);
        logger.info("job finished");
    }
}
3.编写Spring容器配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--创建任务详情-->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!--指定执行任务具体类-->
        <property name="jobClass" value="sustainable.job.SpringClusterQuartzJob"/>
        <!--使用Job状态-->
        <property name="jobDataAsMap">
            <map>
                <entry key="count" value-type="java.lang.Integer" value="0"/>
            </map>
        </property>
        <!--无绑定的触发器也不会删除该任务-->
        <property name="durability" value="true"/>
        <!--再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务-->
        <property name="requestsRecovery" value="false"/>
    </bean>

    <!--创建触发器-->
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"/>
        <property name="cronExpression" value="0/5 * * * * ?"/>
    </bean>

    <!--创建调度器-->
    <bean name="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--
            org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下文以key/value的方式存放在了SchedulerContext中了,
            可以用applicationContextSchedulerContextKey所定义的key得到对应spring的ApplicationContext
        -->
        <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
        <!--指定配置文件位置-->
        <property name="configLocation" value="classpath:quartz.properties" />
        <!--设置触发器-->
        <property name="triggers">
            <list>
                <ref bean="trigger"/>
            </list>
        </property>
        <!--
            设置spring加载即自动启动任务,需要配合bean标签中添加lazy-init="false",一般在web项目中可以添加这个属性让服务已启动就自动启动任务
           <property name="autoStartup" value="true"/>
        -->
    </bean>
</beans>
4.主任务测试
public class SpringClusterQuartzTest {

    public static void main(String[] args){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-cluster.xml");
        Scheduler scheduler = (Scheduler) applicationContext.getBean("scheduler");
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

跑起主任务之后停掉再开,会发现计数记录扔保留,代表持久化起作用了!

然后,尝试开启两个同样项目,当关闭其中一个时候,另外一个会接手执行任务,集群完成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值