定时任务框架

定时任务的框架有哪些

Timer,JDK自带的,比较简单,使用的时候,定义一个TimerTask,实现run方法,然后定义一个Timer类,调用timer.schedule(timerTask,1000,3000);
○ 缺点:单线程、无异常处理,如果执行时间太长或者任务执行异常,会影响其他任务调度
springboot 的 @Scheduled (Spring Task)
使用简单,在启动类上开启,EnableScheduling,然后在使用定时任务的方法上添加`@Scheduled(cron=“xxxxxxx”)
○ 优点:1.简单 2.比Timer准确一点 3.可以配置多线程
○ 缺点:1.无自带异常处理,2.设计上偏向单节点运行
Quartz 框架,是一个完全由Java编写的开源作业调度框架,这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。
○ 优点:1.强大的调度功能 2.灵活的应用方式 3.支持持久化
○ 缺点:需要把任务信息持久化到业务数据库、和业务有耦合、并且表比较多
xxl-job:的组成角色:整体分为两个部分:调度中心执行器,调度中心:可以理解为服务端,需要单独部署,提供的UI界面来管理定时任务,负责发起调度,本身不承接业务逻辑。把调度和任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块。执行器:可以理解为客户端,需要跟我们实际开发的项目整合,负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效;任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑。

下面着重介绍下Quartz以及xxl-job

Quartz

里面有几个核心的概念:Job(任务)表示我们定时要执行的业务逻辑,需要重写execute()方法,Trigger(触发器)表示什么时候执行,Scheduler(调度器)负责把Job和Trigger绑定在一起去执行,保证任务可以在正确的时间执行。
在这里插入图片描述
Job和Trigger关系:一个job可以有多个trigger;一个trigger只能有个一个job;
核心代码

private void openJob(Scheduler scheduler){
    try {
        //1.创建一个JobDetail
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();
        //2.触发器表达式对象
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/4 * * * * ?");
        //CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("30 25 16 * * ?");
        //3.准备一个触发器对象
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggergroup1")
                .withSchedule(cronScheduleBuilder).build();
        //4.开始调度
        scheduler.scheduleJob(jobDetail,cronTrigger);
    } catch (SchedulerException e) {
        e.printStackTrace();
    } finally {

    }
}

通过代码可以看到几个重要的类:
● JobDetail: 真正的任务内容,任务本身是集成Job接口的,但是真正的任务是 JobBuilder通过反射的方式实例化的。
● Trigger: 触发器,定义任务应当开始的时间,主要分为两类 SimpleTrigger,CronTrigger,当前例子的就是简单触发器,CronTrigger主要用于 处理quartz表达式定义的任务,比如每个月20号,每个星期一之类的。
● Scheduler: 计划执行者,现在我们有了要做的内容(HelloJob),有了要做的时间 (下一分钟),接下来,就把这两个内容填充到计划任务Scheduler对象里面,到了时间它就可以自动运行了。

Quartz核心类与方法

暂停Job:------pauseJob(jobKey)

//通过JobName以及JobGroup获得JobKey
   JobKey jobKey = JobKey.jobKey("123", JOB_GROUP_NAME);
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler .pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

恢复Job:-----resumeJob(jobKey)

//通过JobName以及JobGroup获得JobKey
JobKey jobKey = JobKey.jobKey("123", JOB_GROUP_NAME);
try {
    schedulerFactoryBean.getScheduler().resumeJob(jobKey);
} catch (SchedulerException e) {
    e.printStackTrace();
}

删除job------deleteJob(jobKey)/unscheduleJob(triggerkey)

方法一:
//通过JobName以及JobGroup获得JobKey
JobKey jobKey = JobKey.jobKey("123", JOB_GROUP_NAME);
try {
    schedulerFactoryBean.getScheduler().deleteJob(jobKey);
} catch (SchedulerException e) {
    e.printStackTrace();
}
方法二:
//通过triggerName获取TriggerKey
TriggerKey aaatrigger = TriggerKey.triggerKey("aaatrigger");
try {
    schedulerFactoryBean.getScheduler().unscheduleJob(aaatrigger);
} catch (SchedulerException e) {
    e.printStackTrace();
}

JobDetail

JobDetailJob实例提供了许多设置属性,以及JobDetailMap成员变量属性,它用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。

JobDetail属性

name:任务名称
group:任务所属组
jobClass:任务实现类
jobDataMap:传参的作用

JobExecutionContext

Scheduler调用一个Job,就会将JobExecutionContext传递给Jobexecute()方法;
Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。

JobDataMap

在进行任务调度时JobDataMap存储在JobExecutionContext中,非常方便获取
JobDataMap可以用来装载任务可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它
JobDataMap实现了JDKMap接口,并且添加了一些非常方便的方法用来存取基本数据类型

说明:
1、实际上,Quartz在进行调度器初始化的时候,会加载quartz.properties文件进行一些属性的设置,比如Quartz后台线程池的属性(threadCount)、作业存储设置等。它会先从工程中找,如果找不到那么就是用quartz.jar中的默认的quartz.properties文件。
2、Quartz存在监听器的概念,比如任务执行前后、任务的添加等,可以方便实现任务的监控。

XXL-JOB

quartz现有定时任务的缺点:
● 1.各个模块都需要使用QuartzJobConfig配置,调度逻辑和执行任务耦合在一起
● 2.定时任务缓存会影响配置修改
● 3.开关不方便
● 4.没有管理页面

XXL-JOB的优点(特性)

使用简单,支持集群部署;提供运维界面维护成本小;自带错误预警;相对elastic-job来说不需要额外的组件(zookeeper);支持调度策略;支持分片;故障转移 ;更适合分布式。

● 简单:支持通过Web页面对任务进行CRUD操作,支持动态修改任务状态、启动/停止任务,操作简单
● 任务分布式执行,任务”执行器”支持集群部署,支持弹性扩容缩容;
● 丰富的路由策略:包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等
● 任务超时控制:支持自定义任务超时时间,任务运行超时将会主动中断任务
● 任务失败重试:支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;其中分片任务支持分片粒度的失败重试
● 任务失败告警;默认提供邮件方式失败告警,同时预留扩展接口,可方便的扩展短信、钉钉等告警方式
● 分片广播任务:执行器集群部署时,任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务

xxl-job的组成角色:

整体分为两个部分:调度中心 和 执行器
调度中心:可以理解为服务端,需要单独部署,提供的UI界面来管理定时任务,负责发起调度,本身不承接业务逻辑。把调度和任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块。
支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,GLUE开发和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。
执行器:可以理解为客户端,需要跟我们实际开发的项目整合,负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效;接收“调度中心”的执行请求、终止请求和日志请求等。任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑
总结:“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性。

三个文件

  • xxl-job-admin 调度中心
  • xxl-job-core 公共依赖
  • xxl-job-executor-samples 实例–执行器

任务详解

基础配置:
- 执行器:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 “执行器管理” 进行设置;
- 任务描述:任务的描述信息,便于任务管理;
- 负责人:任务的负责人;
- 报警邮件:任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;
触发配置:
- 调度类型:
无:该类型不会主动触发调度;
CRON:该类型将会通过CRON,触发任务调度;
固定速度:该类型将会以固定速度,触发任务调度;按照固定的间隔时间,周期性触发;
固定延迟:该类型将会以固定延迟,触发任务调度;按照固定的延迟时间,从上次调度结束后开始计算延迟时间,到达延迟时间后触发下次调度;
- CRON:触发任务执行的Cron表达式;
- 固定速度:固件速度的时间间隔,单位为秒;
- 固定延迟:固件延迟的时间间隔,单位为秒;
任务配置:
- 运行模式:
BEAN模式:任务以JobHandler方式维护在执行器端;需要结合 “JobHandler” 属性匹配执行器中任务;
GLUE模式(Java):任务以源码方式维护在调度中心;该模式的任务实际上是一段继承自IJobHandler的Java类代码并 “groovy” 源码方式维护,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务;
GLUE模式(Shell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 “shell” 脚本;
GLUE模式(Python):任务以源码方式维护在调度中心;该模式的任务实际上是一段 “python” 脚本;
GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务实际上是一段 “php” 脚本;
GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务实际上是一段 “nodejs” 脚本;
GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 “PowerShell” 脚本;
- JobHandler:运行模式为 “BEAN模式” 时生效,对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值;
- 执行参数:任务执行所需的参数;
高级配置:
- 路由策略:当执行器集群部署时,提供丰富的路由策略,包括;
FIRST(第一个):固定选择第一个机器;
LAST(最后一个):固定选择最后一个机器;
ROUND(轮询):;
RANDOM(随机):随机选择在线的机器;
CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。
LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举;
LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举;
FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;
BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;
- 子任务:每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取),当本任务执行结束并且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。
- 调度过期策略:
- 忽略:调度过期后,忽略过期的任务,从当前时间开始重新计算下次触发时间;
- 立即执行一次:调度过期后,立即执行一次,并从当前时间开始重新计算下次触发时间;
- 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略;
单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;
- 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;
- 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;

xxl-job框架的使用步骤:

1、从GitHub下载对应项目代码

在这里插入图片描述

2、将xxl-job-core编译成jar包,上传到远程仓库(执行器需要应用对应jar包)
3、调度中心部署:

(可以用Jenkins打包发布)
1)将xxl-job-master整体打成jar包(删除xxl-job-excutor-samples模块)
2)对应jar包生成容器镜像
3)在机器上面配置环境变量,然后直接启容器镜像

4、调度项目接入

1)pom文件添加依赖

<!-- xxl-job -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>${xxl.job.core.version}</version>
</dependency>

2)添加java配置及yaml配置

# xxl-job
xxl:
  job:
    ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
    admin.addresses: http://127.0.0.1:8083/xxl-job-admin
    ### xxl-job, access token
    accessToken: jrU2XoTTq2VSuh5n0J83z40jbcZL1Yn1
    executor:
      ### xxl-job executor appname
      appname: xm-ds-executor
      ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
      address:
      ### xxl-job executor server-info
      ip:
      port: 9999
      ### xxl-job executor log-path
      logpath: /data0/logs/xxl-job
      ### xxl-job executor log-retention-days
      logretentiondays: 30

XxlJobConfig.java

@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
    logger.info(">>>>>>>>>>> xxl-job config init.");
    XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
    xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
    xxlJobSpringExecutor.setAppname(appname);
    xxlJobSpringExecutor.setIp(ip);
    xxlJobSpringExecutor.setPort(port);
    xxlJobSpringExecutor.setAccessToken(accessToken);
    xxlJobSpringExecutor.setLogPath(logPath);
    xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
    return xxlJobSpringExecutor;
}

3)代码改造
在原来的quartz代码基础上,加上注解即可。注意注解后面的JobHandler名称需要跟控制台一致。
日志如果要记录到远程记录上面,需要使用对应的日志方法 XxlJobHelper.log(“XXL-JOB, Hello World.”);

@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
    XxlJobHelper.log("XXL-JOB, Hello World.");
}
5、调度中心配置任务触发详情

1)添加执行器(新应用接入,添加后需要过30s左右时间,机器会自动注册过来)
注:此处的AppName需要跟第四步的2)yaml文件里面的appname一致。名称是用于页面其他地方展示执行器的名称
在这里插入图片描述
2)创建任务
注:此处的执行器,选择上一步添加的执行器,然后填写任务描述、负责人、报警邮件(接收人),填写调度配置、任务配置(注解接入属于BEAN模式,JobHandler需要跟第四步的3)里面注解填写的JobHandler名称一致,填写高级配置(路由策略、调度过期策略、阻塞处理策略需谨慎选择),子任务ID一般为空,任务超时时间和失败重试次数根据业务需要填写
在这里插入图片描述
3)任务测试及启动
此处执行一次,相当于手动触发一次立即执行的任务。业务允许的情况下,最好执行一次测试下,看下是否有问题(可以看执行日志)
4)查看执行日志,看下执行是否正常
注:实际的日志是记录到对应的执行器服务器上面的文件的,所以如果执行器未注册到调度中心,日志是看不了的
在这里插入图片描述
5)运行报表,可以用于查看每天任务调度情况
在这里插入图片描述

参考:
https://www.xuxueli.com/index.html

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了一个简单易用的定时任务框架,可以帮助我们方便地在应用程序中创建和管理定时任务Spring Boot定时任务框架基于Spring框架的@Scheduled注解。我们可以通过在方法上添加@Scheduled注解来指定方法的执行时间和频率。@Scheduled注解可以接受多种参数,如cron表达式、固定延迟时间、固定频率等,我们可以根据实际需求选择合适的参数。同时,我们还可以使用@Scheduled注解的其他属性来配置任务的线程池、错误处理以及任务名称等。 使用Spring Boot定时任务框架非常简单。我们只需要在应用程序的配置类或任意一个Bean类中添加@EnableScheduling注解,然后在需要执行定时任务的方法上添加@Scheduled注解即可。框架会自动扫描并注册这些带有@Scheduled注解的方法,按照指定的时间和频率执行任务。 Spring Boot定时任务框架还提供了一些便利的特性。例如,我们可以通过使用@Async注解将定时任务标记为异步执行,提高任务的并发性能。此外,我们还可以通过使用CronExpression和CronTrigger等类,对复杂的定时任务表达式进行解析和处理。 总之,Spring Boot提供的定时任务框架简单易用、功能强大,能够满足各种应用程序的定时任务需求。无论是简单的定时任务还是复杂的计划任务,Spring Boot定时任务框架都能够提供便捷的解决方案,减少我们开发和维护定时任务的工作量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值