集群式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官网下载分发包,下载地址。下载完成后,在压缩包路径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
微信搜索【银河架构师】,发现更多精彩内容。
技术资料领取方法:关注公众号,回复微服务,领取微服务相关电子书;回复MK精讲,领取MK精讲系列电子书;回复JAVA 进阶,领取JAVA进阶知识相关电子书;回复JAVA面试,领取JAVA面试相关电子书,回复JAVA WEB领取JAVA WEB相关电子书。

集群式Quartz定时任务框架实践的更多相关文章
- quartz定时任务框架的使用
quartz定时任务时间设置 这些星号由左到右按顺序代表 : * * * * * * * ...
- quartz定时任务框架的使用以及原理
quartz定时任务时间设置 这些星号由左到右按顺序代表 : * * * * * * * ...
- (2)Spring集成Quartz定时任务框架介绍和Cron表达式详解
在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但 ...
- Spring集成Quartz定时任务框架介绍和Cron表达式详解
原文地址:http://www.cnblogs.com/obullxl/archive/2011/07/10/spring-quartz-cron-integration.html 在JavaEE系统 ...
- Spring_Spring集成Quartz定时任务框架介绍和Cron表达式详解
在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但 ...
- Spring集成Quartz定时任务框架介绍
在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但 ...
- quartz定时任务框架调度机制解析
转自集群调度机制调研及源码分析 quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 qurat ...
- Quartz -----定时任务框架
一.什么是Quartz 由java开发用来执行定时任务,类似于java.util.Timer. 但是相较于Timer,quartz增加了很多功能: 持久性 ...
- maven项目集成Quartz定时任务框架,实现批处理功能
一.Quartz简介 主要做定时任务,即:在指定时间点或时间段,执行某项任务,可设置执行次数.时间间隔等. 二.Springcloud简介 对比传统的.庞大的.复杂的.以ssm或ssh为框架的web项 ...
随机推荐
- 领扣(LeetCode)寻找旋转排序数组中的最小值 个人题解
假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出其中最小的元素. 你可以假设数组中不存在重 ...
- Error: Cannot find module 'less'
这是webpack.config 代码中引入 报错信息(在main.js中引入也是这个报错 解决办法: 安装less: npm install less --save-dev 转自: https:// ...
- 三种方法教你HTML实现点击某一个元素之外触发事件
HTML实现点击某一个元素之外触发事件 大致编写的HTML界面渲染后是这个样子的,我们现在想要实现的需求是点击Button所在的div不会触发事件,而在点击Button所在的div之外的区域时会触发事 ...
- jinjia2
ansible-playbook --become --become-method=su -K copy.yml - hosts: web remote_user: ansible tasks: - ...
- 如何使用C#调用C++类虚函数(即动态内存调用)
本文讲解如何使用C#调用只有.h头文件的c++类的虚函数(非实例函数,因为非虚函数不存在于虚函数表,无法通过类对象偏移计算地址,除非用export导出,而gcc默认是全部导出实例函数,这也是为什么 ...
- 你真的了解Object源码吗
欢迎点赞阅读,一同学习交流,有疑问请留言 . GitHub上也有开源 JavaHouse 欢迎star 引入 Object 应该是比较简单的源码了.现在我们来分析一下他.Object 是类层次结构的根 ...
- react之context
context是什么 Props属性是由上到下单向传递的 context提供了在组件中共享此类值的方法 context使用 设计目的是共享哪些对于组件来说全局的数据 不要因为仅仅为了避免在几个层级下的 ...
- 带着canvas去流浪系列之四 绘制散点图
[摘要] 用原生canvasAPI实现百度Echarts图表 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI ...
- 挑战10个最难的Java面试题(附答案)【下】
查看挑战10个最难的Java面试题(附答案)[上] 在本文中,我们将从初学者和高级别进行提问, 这对新手和具有多年 Java 开发经验的高级开发人员同样有益. 关于Java序列化的10个面试问题 大多 ...
- 洛谷 题解 P1842 【奶牛玩杂技】
本蒟蒻又双叒叕被爆踩辣! Solution: 我们先看数据,50000,那么O(n)或者O(n log(n))是可以过的,非严格O(n * sqrt(n))要卡卡常,说不定也可以过. 那么什么算法可以 ...