• 集群式Quartz定时任务框架实践


     在日常开发汇总,经常会遇到需要定时任务的场景,简单的,可以使用Spring的定时任务调度框架,也可以使用Quartz。无论使用哪种,都需要解决一个问题,那就是集群问题。一般情况下,定时任务能且仅能运行于一台应用实例上。

    前提

    本文工程基于spring boot 2.1.7.RELEASE

     

    工程配置

     一、pom依赖

     

    如下图所示:

     

    二、yml配置

     

    yml配置如下图所示:

     

    三、quartz.properties

     

    quartz相关属性配置如图:

     

    注意:

    1、重中之重,要设置org.quartz.jobStore.isClustered=true,开启集群模式

    2、其它配置见释义

     

    四、调度器配置

     

    使用SchedulerFactoryBeanCustomizer个性化调度器

    @Configuration
    public class SysConfig {
    
        private final DataSource dataSource;
    
        public SysConfig(DataSource dataSource) {
            this.dataSource = dataSource;
        }
    
        @Bean
        public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() {
            return (schedulerFactoryBean) -> {
                schedulerFactoryBean.setDataSource(dataSource);
                schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
            };
        }
    
    }

     

    五、系统启动

     

    系统启动,如显示quartz以cluster模式启动,则证明配置成功。如图所示:

     

    编写任务

     

    一、Job

     

    代码如下:

    package com.luas.quartz.cluster.demo.quartz.job;
    
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    public class UserJob extends QuartzJobBean {
    
        @Value("${server.port}")
        private String port;
    
        private String name;
    
        private Integer age;
    
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            System.out.println(String.format("the user job is execute on port %s. it's name is %s, age is %s", port, name, age));
        }
    
        public String getPort() {
            return port;
        }
    
        public void setPort(String port) {
            this.port = port;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }

     

    二、Controller触发

     代码如下:

    package com.luas.quartz.cluster.demo.controller;
    
    import com.luas.quartz.cluster.demo.quartz.job.UserJob;
    import org.quartz.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.time.LocalDateTime;
    
    @RestController
    @RequestMapping("/job")
    public class JobController {
    
        @Autowired
        private Scheduler scheduler;
    
        @RequestMapping("/user")
        public Object user() throws Exception {
            JobBuilder jobBuilder = JobBuilder
                    .newJob(UserJob.class)
                    .withIdentity(new JobKey("UserJob", "default"))
                    .withDescription("a demo quartz job")
                    .storeDurably();
    
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("name", "luas");
            jobDataMap.put("age", 18);
    
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger()
                    .withIdentity(new TriggerKey("UserJob's trigger 1", "default"))
                    .withSchedule(createSimpleScheduleBuilder())
                    .forJob(new JobKey("UserJob", "default"))
                    .usingJobData(jobDataMap)
                    .startNow();
    
            this.scheduler.scheduleJob(jobBuilder.build(), triggerBuilder.build());
    
            return LocalDateTime.now();
        }
    
        private ScheduleBuilder createSimpleScheduleBuilder() {
            SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInMilliseconds(10000)
                    .withRepeatCount(100);
    
            return simpleScheduleBuilder;
        }
    
    }

     

    三、系统启动

     

    依次启动8080、8082两个实例。idea默认只能启动一个实例,需要配置并行运行才可以运行两个相同的实例,如下图所示,勾选Allow parallel run即可。

     

    访问:http://localhost:8080/quartz/job/user,页面返回当前时间。

    此时,8080和8082控制台信息分别如图所示:

    8080:

     

    8082:

     

    可以看出,Quartz运行在8080实例上,而8082实例处于监控状态。

     

    四、切换运行实例

     

     停止8080实例,手工模拟服务器故障,观察8082实例控制台输出,发现quartz已经运行在8082实例上,如图所示:

     8080停止:

     

    8082接管:

     

     

    问题

     

    1、启动报错:Couldn't store job: JobDataMap values must be Strings when the 'useProperties' property is set.

     修改quartz.properties配置中org.quartz.jobStore.useProperties=false

     

     2、UserJob中@Value注解标注的port属性如何会自动注入、name、age属性如何会自动注入?

     参考QuartzAutoConfiguration、SpringBeanJobFactory类的如下片段:

     

    3、数据结构

     Quartz官网下载分发包,下载地址。下载完成后,在压缩包路径docsdbTables下,有各个数据库相对应的脚本文件,选择自己对应的脚本执行即可。如本文选择的为tables_mysql_innodb.sql。

     

    其它

    一、源码

     本文源码地址如下:

    • github:https://github.com/liuminglei/learning-demo/tree/master/quartz-cluster-demo

    • gitee:https://gitee.com/xbd521/learning-demo/tree/master/quartz-cluster-demo

    二、集成框架

     基于quartz的集群式、非集群式轻量封装定时任务调度框架-quartz、quartz-boot已共享,配置、操作更便捷、高效,欢迎star、fork。

     quartz-boot:

    • github:https://github.com/liuminglei/quartz-boot

    • gitee:https://gitee.com/xbd521/quartz-boot

     quartz

    • github:https://github.com/liuminglei/quartz

    • gitee:https://gitee.com/xbd521/quartz

     

    本文由【银河架构师】原创,转载请注明作者及出处。另附本文地址:

    https://www.cnblogs.com/luas/p/12040304.html

    微信搜索【银河架构师】,发现更多精彩内容。

    技术资料领取方法:关注公众号,回复微服务,领取微服务相关电子书;回复MK精讲,领取MK精讲系列电子书;回复JAVA 进阶,领取JAVA进阶知识相关电子书;回复JAVA面试,领取JAVA面试相关电子书,回复JAVA WEB领取JAVA WEB相关电子书。

     

     
  • 相关阅读:
    Power Apps 创建响应式布局
    SharePoint Online 软件边界限制
    Power Apps 中人员选择器的使用
    Power Apps 中修改 SharePoint Online 数据
    Power Apps 中调用 Automate 工作流
    如何查看你的Office 365 账号的订阅
    Microsoft Teams 中嵌入SharePoint Online 页面
    SharePoint Online 触发Outlook邮件内审批
    Linux查看实时网卡流量的几种方式
    Linux性能优化和监控系列(三)——分析Memory使用状况
  • 原文地址:https://www.cnblogs.com/luas/p/12040304.html
Copyright © 2020-2023  润新知