在日常开发汇总,经常会遇到需要定时任务的场景,简单的,可以使用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官网下载分发包,下载地址。下载完成后,在压缩包路径docs\dbTables下,有各个数据库相对应的脚本文件,选择自己对应的脚本执行即可。如本文选择的为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
微信搜索【银河架构师】,发现更多精彩内容。
原文地址:https://www.cnblogs.com/luas/p/12040304.html