SpringBoot 整合 Quartz 实现分布式调度(五)

简介: 阅读完本文大概需要 10 分钟,本文主要分享内容如下: springboot + quartz + mysql 实现持久化分布式调度 集群环境任务调度测试

4.11、注册监听器(选用)

当然,如果你想在 SpringBoot 里面集成 Quartz 的监听器,操作也很简单!

  • 创建任务调度监听器
@Component
public class SimpleSchedulerListener extends SchedulerListenerSupport {
    @Override
    public void jobScheduled(Trigger trigger) {
        System.out.println("任务被部署时被执行");
    }
    @Override
    public void jobUnscheduled(TriggerKey triggerKey) {
        System.out.println("任务被卸载时被执行");
    }
    @Override
    public void triggerFinalized(Trigger trigger) {
        System.out.println("任务完成了它的使命,光荣退休时被执行");
    }
    @Override
    public void triggerPaused(TriggerKey triggerKey) {
        System.out.println(triggerKey + "(一个触发器)被暂停时被执行");
    }
    @Override
    public void triggersPaused(String triggerGroup) {
        System.out.println(triggerGroup + "所在组的全部触发器被停止时被执行");
    }
    @Override
    public void triggerResumed(TriggerKey triggerKey) {
        System.out.println(triggerKey + "(一个触发器)被恢复时被执行");
    }
    @Override
    public void triggersResumed(String triggerGroup) {
        System.out.println(triggerGroup + "所在组的全部触发器被回复时被执行");
    }
    @Override
    public void jobAdded(JobDetail jobDetail) {
        System.out.println("一个JobDetail被动态添加进来");
    }
    @Override
    public void jobDeleted(JobKey jobKey) {
        System.out.println(jobKey + "被删除时被执行");
    }
    @Override
    public void jobPaused(JobKey jobKey) {
        System.out.println(jobKey + "被暂停时被执行");
    }
    @Override
    public void jobsPaused(String jobGroup) {
        System.out.println(jobGroup + "(一组任务)被暂停时被执行");
    }
    @Override
    public void jobResumed(JobKey jobKey) {
        System.out.println(jobKey + "被恢复时被执行");
    }
    @Override
    public void jobsResumed(String jobGroup) {
        System.out.println(jobGroup + "(一组任务)被恢复时被执行");
    }
    @Override
    public void schedulerError(String msg, SchedulerException cause) {
        System.out.println("出现异常" + msg + "时被执行");
        cause.printStackTrace();
    }
    @Override
    public void schedulerInStandbyMode() {
        System.out.println("scheduler被设为standBy等候模式时被执行");
    }
    @Override
    public void schedulerStarted() {
        System.out.println("scheduler启动时被执行");
    }
    @Override
    public void schedulerStarting() {
        System.out.println("scheduler正在启动时被执行");
    }
    @Override
    public void schedulerShutdown() {
        System.out.println("scheduler关闭时被执行");
    }
    @Override
    public void schedulerShuttingdown() {
        System.out.println("scheduler正在关闭时被执行");
    }
    @Override
    public void schedulingDataCleared() {
        System.out.println("scheduler中所有数据包括jobs, triggers和calendars都被清空时被执行");
    }
}
  • 创建任务触发监听器
@Component
public class SimpleTriggerListener extends TriggerListenerSupport {
    /**
     * Trigger监听器的名称
     * @return
     */
    @Override
    public String getName() {
        return "mySimpleTriggerListener";
    }
    /**
     * Trigger被激发 它关联的job即将被运行
     * @param trigger
     * @param context
     */
    @Override
    public void triggerFired(Trigger trigger, JobExecutionContext context) {
        System.out.println("myTriggerListener.triggerFired()");
    }
    /**
     * Trigger被激发 它关联的job即将被运行, TriggerListener 给了一个选择去否决 Job 的执行,如果返回TRUE 那么任务job会被终止
     * @param trigger
     * @param context
     * @return
     */
    @Override
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
        System.out.println("myTriggerListener.vetoJobExecution()");
        return false;
    }
    /**
     * 当Trigger错过被激发时执行,比如当前时间有很多触发器都需要执行,但是线程池中的有效线程都在工作,
     * 那么有的触发器就有可能超时,错过这一轮的触发。
     * @param trigger
     */
    @Override
    public void triggerMisfired(Trigger trigger) {
        System.out.println("myTriggerListener.triggerMisfired()");
    }
    /**
     * 任务完成时触发
     * @param trigger
     * @param context
     * @param triggerInstructionCode
     */
    @Override
    public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
        System.out.println("myTriggerListener.triggerComplete()");
    }
}
  • 创建任务执行监听器
@Component
public class SimpleJobListener extends JobListenerSupport {
    /**
     * job监听器名称
     * @return
     */
    @Override
    public String getName() {
        return "mySimpleJobListener";
    }
    /**
     * 任务被调度前
     * @param context
     */
    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        System.out.println("simpleJobListener监听器,准备执行:"+context.getJobDetail().getKey());
    }
    /**
     * 任务调度被拒了
     * @param context
     */
    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        System.out.println("simpleJobListener监听器,取消执行:"+context.getJobDetail().getKey());
    }
    /**
     * 任务被调度后
     * @param context
     * @param jobException
     */
    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        System.out.println("simpleJobListener监听器,执行结束:"+context.getJobDetail().getKey());
    }
}
  • 最后,将监听器注册到Scheduler
@Autowired
private SimpleSchedulerListener simpleSchedulerListener;
@Autowired
private SimpleJobListener simpleJobListener;
@Autowired
private SimpleTriggerListener simpleTriggerListener;
@Bean(name = "scheduler")
public Scheduler scheduler() throws IOException, SchedulerException {
    Scheduler scheduler = schedulerFactoryBean().getScheduler();
    //全局添加监听器
    //添加SchedulerListener监听器
    scheduler.getListenerManager().addSchedulerListener(simpleSchedulerListener);
    // 添加JobListener, 支持带条件匹配监听器
    scheduler.getListenerManager().addJobListener(simpleJobListener, KeyMatcher.keyEquals(JobKey.jobKey("myJob", "myGroup")));
    // 添加triggerListener,设置全局监听
    scheduler.getListenerManager().addTriggerListener(simpleTriggerListener, EverythingMatcher.allTriggers());
    return scheduler;
}

4.12、采用项目数据源(选用)

在上面的 Quartz 数据源配置中,我们使用了自定义的数据源,目的是和项目中的数据源实现解耦,当然有的同学不想单独建库,想和项目中数据源保持一致,配置也很简单!

  • quartz.properties配置文件中,去掉org.quartz.jobStore.dataSource配置
#注释掉quartz的数据源配置
#org.quartz.jobStore.dataSource=qzDS
  • QuartzConfig配置类中加入dataSource数据源,并将其注入到quartz
@Autowired
private DataSource dataSource;
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
    //...
    SchedulerFactoryBean factory = new SchedulerFactoryBean();
    factory.setQuartzProperties(propertiesFactoryBean.getObject());
    //使用数据源,自定义数据源
    factory.setDataSource(dataSource);
    //...
    return factory;
}


五、任务调度测试

在实际的部署中,项目都是集群进行部署,因此为了和正式环境一致,我们再新建两个相同的项目来测试一下在集群环境下 quartz 是否可以实现分布式调度,保证任何一个定时任务只有一台机器在运行

理论上,我们只需要将刚刚新建好的项目,重新复制一份,然后修改一下端口号就可以实现本地测试!

因为curd服务只需要一个,因此我们不需要再编写QuartzJobService等增、删、改服务,仅仅保持QuartzConfigDruidConnectionProviderQuartzJobFactoryTfCommandJobquartz.properties类和配置都是相同的就可以了!


91.jpg

  • 依次启动服务quartz-001quartz-002quartz-003,看看效果如何

第一个启动的服务quartz-001会优先加载数据库中已经配置好的定时任务,其他两个服务quartz-002quartz-003都没有主动调度服务

92.jpg


quartz-001

  • 当我们主动关闭quartz-001quartz-002服务主动接收任务调度

94.jpg

quartz-002

  • 当我们主动关闭quartz-002,同样quartz-003服务主动接收任务调度

95.jpg



quartz-003

最终结果,和我们预期效果一致!

六、小结

本文主要围绕springboot + quartz + mysql实现持久化分布式调度进行介绍,所有的代码功能,笔者都亲自测试过,可能内容比较多,鉴于笔者才疏学浅,如果有遗漏的地方,欢迎网友批评指出!

相关文章
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
3月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
126 1
|
18天前
|
存储 NoSQL Java
Java调度任务如何使用分布式锁保证相同任务在一个周期里只执行一次?
【10月更文挑战第29天】Java调度任务如何使用分布式锁保证相同任务在一个周期里只执行一次?
46 1
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
2月前
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
232 1
|
4月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14959 29
|
3月前
|
Java 微服务 Spring
SpringBoot+Vue+Spring Cloud Alibaba 实现大型电商系统【分布式微服务实现】
文章介绍了如何利用Spring Cloud Alibaba快速构建大型电商系统的分布式微服务,包括服务限流降级等主要功能的实现,并通过注解和配置简化了Spring Cloud应用的接入和搭建过程。
SpringBoot+Vue+Spring Cloud Alibaba 实现大型电商系统【分布式微服务实现】
|
3月前
|
机器学习/深度学习 资源调度 PyTorch
面向大规模分布式训练的资源调度与优化策略
【8月更文第15天】随着深度学习模型的复杂度不断提高,对计算资源的需求也日益增长。为了加速训练过程并降低运行成本,高效的资源调度和优化策略变得至关重要。本文将探讨在大规模分布式训练场景下如何有效地进行资源调度,并通过具体的代码示例来展示这些策略的实际应用。
390 1
|
3月前
|
Java 关系型数据库 MySQL
SpringBoot 集成 Quartz + MySQL
SpringBoot 集成 Quartz + MySQL
116 1
|
3月前
|
Dubbo Java 调度
揭秘!Spring Cloud Alibaba的超级力量——如何轻松驾驭分布式定时任务调度?
【8月更文挑战第20天】在现代微服务架构中,Spring Cloud Alibaba通过集成分布式定时任务调度功能解决了一致性和可靠性挑战。它利用TimerX实现任务的分布式编排与调度,并通过`@SchedulerLock`确保任务不被重复执行。示例代码展示了如何配置定时任务及其分布式锁,以实现每5秒仅由一个节点执行任务,适合构建高可用的微服务系统。
69 0

热门文章

最新文章

下一篇
无影云桌面