集群部署项目时,Spring Task的坑

这篇具有很好参考价值的文章主要介绍了集群部署项目时,Spring Task的坑。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 通过Spring Task执行定时任务

1.创建定时任务

我们要在下面的代码中,实现每5秒钟执行一个打印信息的任务。

package com.qfedu.day85.task;

import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class PrintTask {

    // 任务默认同步执行的
    @Async  // 表示异步执行的注解
    // 每分钟的第5秒触发定时任务
    @Scheduled(cron = "5 * * * * ?")
    public void printInfo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
        System.out.println(sdf.format(new Date()) + ": print info test");
    }
}

2.启动同一个项目的多个实例
首先我们可以通过“Edit Configurations”,增加一个运行实例的配置。

集群部署项目时,Spring Task的坑,Java,spring,java,后端


接着启动项目的多个实例即可,如下图所示:

集群部署项目时,Spring Task的坑,Java,spring,java,后端

3.查看执行结果
然后我们就可以查看上面代码的执行结果了,如下图:

集群部署项目时,Spring Task的坑,Java,spring,java,后端

集群部署项目时,Spring Task的坑,Java,spring,java,后端


通过对比执行结果,我们会发现,有两个实例"同时"执行了任务。实际开发中,我们的项目经常会进行集群部署,但是,如果我们通过Spring Task来执行定时任务,只需要一个实例执行任务即可。
那么,如果我们不想有多个实例同时执行任务,需要怎么办呢?
一般我们可以借助分布式锁对任务进行加锁,防止多个实例同时执行任务。
但这样做,真的可以吗?

二. 定时任务中使用分布式锁

1.通过Redisson对任务加锁
加锁后的代码如下:

package com.qfedu.day85.task;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
public class PrintTask {
    // 注入RedissonClient 对象
    @Resource
    private RedissonClient redissonClient;

    @Async
    @Scheduled(cron = "0/5 * * * * ?")
    public void printInfo2() {
        // 获取锁对象,参数表示redis中key值
        RLock taskLock = redissonClient.getLock("taskLock");

        try {
            // 尝试加锁,
            // 第一个参数,表示加锁的重试时间,如果锁被占用,在指定时间内尝试加锁
            // 第二个参数,表示锁过期时间
            // 返回true/false
            // 本例中,第一个参数是0,表示如果没有加上锁,直接返回false
            if (taskLock.tryLock(0, 10, TimeUnit.SECONDS)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                System.out.println(sdf.format(new Date()) + ": print info test");
                // Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (taskLock.isLocked()) {
                // 判断是否当前线程拥有该锁
                if (taskLock.isHeldByCurrentThread()) {
                    // 释放锁
                    taskLock.unlock();
                }
            }
        }
    }
}

本例,不讨论Redisson的使用。

2. 执行结果

集群部署项目时,Spring Task的坑,Java,spring,java,后端

集群部署项目时,Spring Task的坑,Java,spring,java,后端


通过上图的执行结果,我们发现,虽然使用了分布式锁,但在某些时间点,比如“17:38:15”,两个实例还是“同时”执行了相同的任务。
难道分布式锁没有起作用?当然不是,真相其实是这个样子的......
我们的任务执行的太快了!!!
Day85Application2这个实例,在17:38:15.008时对任务加锁并且执行,任务很快执行完毕。Day85Application这个实例,在17:38:15.029执行任务,加锁时,发现锁没被占用,于是又执行了一次任务。
通过上面的分析,我们会发现,如果任务执行时间很短,在一秒内多个实例可以多次加锁并执行任务,于是就出现了在同一秒内,任务“同时”执行的现象。
 

集群部署项目时,Spring Task的坑,Java,spring,java,后端


3. 解决方案
要想解决上述问题,我们可以把代码稍微改一下:
 

集群部署项目时,Spring Task的坑,Java,spring,java,后端


修改方案如上图代码所示,让任务强行休眠1秒。再次执行,你就发现,现在已经不会出现同一秒内任务“同时”执行的现象了。
但是,这种做法实在是有辱斯文。如果项目需要进行集群部署,我们在使用定时任务时,最好还是使用第三方的分布式任务框架,比如quartz、xxl-job等。
以上只是一家之言,如有不当之处,欢迎老铁们在评论区留言或私信给我。

视频教程传送门:Spring教程入门到精通,一套搞定spring(源码实战讲解)

 文章来源地址https://www.toymoban.com/news/detail-612925.html

到了这里,关于集群部署项目时,Spring Task的坑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java版企业工程项目管理系统源码+java版本+项目模块功能清单+spring cloud +spring boot

          工程项目各模块及其功能点清单 一、系统管理     1、数据字典:实现对数据字典标签的增删改查操作     2、编码管理:实现对系统编码的增删改查操作     3、用户管理:管理和查看用户角色     4、菜单管理:实现对系统菜单的增删改查操作     5、角色管理:

    2024年02月16日
    浏览(48)
  • idea使用Spring Initializer创建springboot项目的坑【保姆级教学】

    提示:这里先简述项目创建后遇到的问题和解决方案: idea 使用 Spring Initializer 创建springboot项目后, 有以下问题: ① 右键没有Run ② 右键New新建文件发现无Java Class选项 然后解决掉 ①② 问题后出现新的问题: ③ @SpringBootApplication 注解爆红找不到引用 ④ pom依赖能下载但是加

    2024年02月04日
    浏览(56)
  • 基于SpringBoot+WebSocket+Spring Task的前后端分离外卖项目-订单管理(十七)

    1.1 介绍 Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。 定位 :定时任务框架 作用 :定时自动执行某段Java代码 应用场景: 1). 信用卡每月还款提醒 2). 银行贷款每月还款提醒 3). 火车票售票系统处理未支付订单 4). 入职纪念日为用户发

    2024年02月21日
    浏览(54)
  • 使用spring-kafka的Java API操作Kafka集群的Topic

    记录 :462 场景 :在Spring Boot微服务集成spring-kafka-2.8.2操作Kafka集群的Topic的创建和删除。 版本 :JDK 1.8,Spring Boot 2.6.3,kafka_2.12-2.8.0,spring-kafka-2.8.2。 Kafka集群安装 :https://blog.csdn.net/zhangbeizhen18/article/details/131156084 1.微服务中 配置Kafka信息 1.1在pom.xml添加依赖 pom.xml文件: 解析:

    2024年02月10日
    浏览(42)
  • 初级 - 若依框架 - Java Spring/Spring Boot 项目理解记录

    一般情况下,我们创建对象都是 类名 + 类引用名 = new 类名() 但是如果是不想要 等于号后面的对象实例化操作,那么可以使用 @Autowired 注解,当然这是在使用 Spring 时,才能这样,不然一般情况下,也没法用这个注解。用了这个 @Autowired 注解,会让 Spring 自动帮你托管这个对象

    2024年02月16日
    浏览(50)
  • 网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(四)对战模块

    匹配成功返回数据 1. message消息类别 2. ok 3. reson 4. 房间id 5. 双方id 6.白色玩家 一个类记录房间中的信息(房间id,两个用户id,是否为白棋) 信息提示框 处理匹配API 初始化游戏(棋盘,下一个棋子,接受棋子处理响应,判断是否结束) 1. 客户端连接到游戏房间后, 服务器返回

    2024年02月13日
    浏览(51)
  • Lucky player —— Java 项目(Spring Boot)

    项目名称 :lucky player 项目的主要功能 :本系统主要功能为构建了一个用户分享音乐的平台,普通用户不进行登录即可收听其他用户已经发布的专辑中的音乐。  作为博主则可以在该平台上传音频,以及在线音频录制上传。音频上传成功后,博主可以把自己的音频整理到一个

    2024年02月11日
    浏览(42)
  • 使用Spring Boot和Docker快速部署Java应用程序

    随着微服务的兴起,容器化技术已成为现代应用程序开发和部署的关键部分。Docker作为一种流行的容器化解决方案,广泛应用于企业和开发者社区。与此同时,Spring Boot作为一种优秀的Java开发框架,大大简化了基于Spring的应用程序开发。在本文中,我们将探讨如何将Spring Bo

    2024年02月01日
    浏览(59)
  • Spring boot项目java bean和xml互转

    工作中需要给下游第三方收费系统做数据挡板,由于下游系统使用的是 soap webservice ,里面涉及各种xml跟bean的互转,在此介绍一下使用的方法。 基于springboot搭建webservice的过程将会在下篇博客介绍 这里介绍两种方法. 使用 jackson 进行互转, Spring boot 项目自带的 json 和 bean 的互

    2024年01月19日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包