定时任务《八》

在实际项目中经常会需要在具体的时间点执行某程序,如每周报表统计等。spring boot 提供了spring task 来解决单机情况下的定时任务需求,在分布式架构中,则可以使用QuartZ 来协调调度多个定时任务从而避免重复计算的问题。

@EnableScheduling:扫描所有的Scheduled注解,使定时任务生效,该注解也可以配置在spring boot 入口处。

@Scheduled[配置方法上,根据设定的规则将定时调用该方法]

 

fixedRate

指定定时任务的循环间隔时间,以时间点为判断标准

FixedDelay

指定定时任务的循环间隔时间,以方法执行结束后为判断标准

initiaIDelay

初始化定时任务的延迟执行时间

Zone

指定cron表达式所处的时区,如果为空,则使用当前机器的默认时区

Cron

指定cron表达式以支持更为丰富的定时规则,以方法执行结束后为判断标准

cron 表达式

一个cron 表达式由6-7个有空分隔的时间元素组成:{秒}{分}{时}{日}{月}{周}{年(可选)}

例如:0 30 01 *  * ?      表示为:每天的凌晨1点三十分执行定时任务。

每位时间元素描述

字段

是否

取值范围

允许的特殊字符

1

0-59

,- * /

2

0-59

,- * /

3

0-23

,- * /

4

1-31

,- * /?

5

1-12或JAN-DEC

,- * /

6

1-7 或 MON-SUN

,- * /?

7

空 或 1970-2099

,- * /

特殊字符描述

*

对应字段上的所有值,例如在分钟字段,表示每一分钟。相应的有每一秒,每个月,每一年等

表示该字段不设置。在两个字段只能选其一的情况下使用,例如日期和星期只能出现一个,那个不使用的那个字段就设置为?

-

用于设置范围,上下界都包含,例如月份字段8-10,表示8,9,10 三个月份

,

表示列表值(多值),如mon,wed,fri表示周一,周三,周五,当取值不连续无法使用范围时,使用该字段

/

配置步长/增量。格式为:开始/步长。在秒位置上配置为0/15,表示从0开始,15为单位增加,在取值范围内的所有值,即1,15,30,45,而5/15,则取值为5,20,35,50

示例:

0 * * * * *

每分钟

0 0 * * * *

每小时

0 /10 * * * * *

每10秒

0 5/15 * * * *

每小时的5分,20分,35分,50分

0 0 9,13 * * *

每天的九点和13点

0 0 8-10 * * *

每天的八点,九点,十点

0 0/30 8-10 * * *

每天的8点,8点半,9点,9点半,10点

0 0 9-17 * * mon-fri

每周一到周五的9点,10点直到17点

0 10,44 14 ? 3 wed

每年3月份每周三的14:10 和14:44

0 0 0 25 12 ?

每年12月25的0点0分0秒

0 30 10 * * ?2017

2017年每天的10点半

QuartZ 分布式定时任务

在分布式模式下spring task 并不适用,而quartz 框架则提供了非常好的分布式定时任务解决方案。

在分布式模式中为了提高系统的可用性,往往一个应用回部署成多个实例,而每个实例中都拥有相同的定时任务,因此肯定回发生定时任务被重复执行的情况。为了解决这一问题,可以在定时任务处理具体业务逻辑之前先向redis获得一个全局锁,各个实例在触发定时任务后谁先获得全局锁则执行业务逻辑,而其他实例则需要等待解锁,以此达到单实例执行定时任务的目的。但是定时任务是由时间驱动触发的,在获取全局锁时又会遇到并发请求的问题,在此可以适用消息队列将并发获取锁的过程转为队列获取。同时在各个定时任务实例中,如果有的实例在获取到全局锁后崩溃,则可能导致原本要执行的任务没有执行。现在需要在redis 中提供定时任务执行结果的字段,实现崩溃转移机制,当某一实例在获取全局锁后发生崩溃,则将该任务交由其他实例执行。

QuartZ 并未与spring boot 集成,在此以spring4.x 和 QuartZ2.x.x 版本示例配置。

1.导入MySQL数据表

分布式模式下QuartZ需要数据库存储定时任务信息,以达到集群调度的目的。目前支持:MySQL,H2,DB2,SQL server,Oracle,Sybase 等数据库。

解压下载好的QuartZ压缩包,导入C:\tools\QuartZ\quartz-2.2.3\docs\dbTables 目录下的tables_mysql_innodb.sql 文件到MySQL。

导入MySQL步骤:打开MySQL--新建连接--新建数据库--选中表--右键--运行SQL文件--选中tables_mysql_innodb.sql--开始。

导入成功后获取的如下表

qrtz_calendars

 

存储quartz的日历信息

qrtz_cron_triggers

 

存储cron表达式与时区信息

qrtz_fired_triggers

 

存储已触发的触发器信息及任务执行信息

qrtz_paused_trigger_grps

 

存储已暂停的触发器组信息

qrtz_scheduler_state

 

调度器状态

qrtz_locks

 

存储程序的悲观锁的信息

qrtz_job_details

 

存储每一个已配置的任务详细信息

qrtz_simple_triggers

 

存储触发器的重复次数,间隔,以及已触发的次数

qrtz_blob_triggers

 

触发器作为blob类型存储

qrtz_triggers

 

存储已配置的触发器信息

qrtz_simprop_triggers

 

触发器监听器

项目中pom 引入:

<!--quartz begin-->
<dependency>
   <groupId>org.quartz-scheduler</groupId>
   <artifactId>quartz</artifactId>
   <version>2.3.0</version>
</dependency>

<dependency>
   <groupId>org.quartz-scheduler</groupId>
   <artifactId>quartz-jobs</artifactId>
   <version>2.3.0</version>
</dependency>

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--quartz end-->

新建quartz.properties:

##实例名称
org.quartz.scheduler.instanceName=spring-boot-quartz-demo
##为每个实例分配一个不重复的id
org.quartz.scheduler.instanceId=AUTO
##跳过更新检查
org.quartz.scheduler.skipUpdateCheck=true
##线程池管理策略
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
##最大线程池数量
org.quartz.threadPool.threadCount=5
##线程优先级
org.quartz.threadPool.threadPriority=5
##触发规则超时时间
org.quartz.jobStore.misfireThreshold=60000
##是否开启集群模式
org.quartz.jobStore.isClustered=true
##实例检查频率
org.quartz.jobStore.clusterCheckinInterval=true

AutoWireCapableBeanFactory :定义了将容器中的bean 按某种规则(按名字,类型匹配等)进行自动封装的方法。

setApplicationContext :来自spring 的applicationContextAwre 接口,通过getAutowireCapableBeanFactory()获得bean的依赖注入。

createJobInstance :来自QuartZ 的springBeanJobFactory类,在创建任务实例时交由spring自动注入。

测试运行:启动多个该spring boot 定时任务应用后,观察控制台输出内容,会发现同一时间内只有一个实例在执行定时任务输出的当前时间,而其他的则在等待。

将当前正在执行定时任务的实例强行关闭后,回发现其他正在运行的某一实例接管了定时任务,继续打印当前时间。

项目展示:https://download.csdn.net/download/qq_35781178/10570504

QuartZ压缩包下载地址:http://www.quartz-scheduler.org/downloads/

上一篇:https://mp.csdn.net/postedit/81263747

猜你喜欢

转载自blog.csdn.net/qq_35781178/article/details/81265167