集群部署项目时,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等。

以上只是一家之言,如有不当之处,欢迎老铁们在评论区留言或私信给我。文章来源地址https://www.toymoban.com/news/detail-653881.html

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

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

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

相关文章

  • idea使用Spring Initializer创建springboot项目的坑【保姆级教学】

    idea使用Spring Initializer创建springboot项目的坑【保姆级教学】

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

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

    基于SpringBoot+WebSocket+Spring Task的前后端分离外卖项目-订单管理(十七)

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

    2024年02月21日
    浏览(13)
  • 使用Docker部署前端项目实战教程,该踩的坑我都帮你踩了!

    使用Docker部署前端项目实战教程,该踩的坑我都帮你踩了!

    每个人的前半生,都在不停地做加法。可到了后半生,我们就要学会不断地做减法。 目录 前置工作 1、需要准备的东西 2、连接云服务器 安装Docker环境  1、安装Docker的依赖库。 2、添加Docker CE的软件源信息。  3、安装Docker CE。 4、启动Docker服务。 准备Dockerfile并部署项目(构

    2023年04月08日
    浏览(12)
  • 切片有哪些注意事项是一定要知道的呢

    在之前我写了一篇 切片比数组好用在哪 的文章,仔细介绍了切片相比于数组的优点。但切片事实上也隐藏着一些潜在的陷阱和需要注意的细节,了解和掌握切片的使用注意事项,可以避免意外的程序行为。本文将深入探讨Go语言切片常见的注意事项,从而能够更好得使用切片

    2024年02月08日
    浏览(9)
  • 单体项目和多模块项目jar包补丁部署注意事项

    单体项目和多模块项目jar包补丁部署注意事项

    目前接触的项目结构主要有单体项目和多模块项目,且这些项目是部署在网络环境一般的服务器上,随着项目规模变大,单个jar的体积动辄就上百MB,每一次代码小改动不可能都上传整个jar,每次代码改动后可能就是把编译后的class文件在服务器上做一个替换,或者直接使用

    2024年01月21日
    浏览(11)
  • 使用ES Term query查询时一定要注意的地方

    使用ES Term query查询时一定要注意的地方

    使用 Term query 可以根据精确值查找相关文档数据,不过 Term query 查询与 Match query 查询还是有区别的,有时候你会发现用 Match query 可以查到,换成 Term query 却不行,本文整理一些使用 Term query 容易出错的点供参考。 如果你查看 Term query 的官方文档,你就会发现,官网首先对

    2024年02月11日
    浏览(9)
  • C++Qt QSS要注意的坑

    qss源自css,相当于css的一个子集,主要支持的是css2标准,很多网上的css3的标准的写法在qss这里是不生效的,所以不要大惊小怪。 qss也不是完全支持所有的css2,比如text-align官方文档就有说明,只支持 QPushButton and QProgressBar,务必看清楚。 有时候偷懒直接来一句 *{xxx},你会发

    2024年02月10日
    浏览(12)
  • RestTemplate进行post请求调用需要注意的坑

    RestTemplate进行post请求调用需要注意的坑

            项目上需要写一个大屏批量、定时调用接口的websocket,为了方便,决定使用spring自带的RestTemplate来完成http请求。get请求时,没那么多需要注意的地方。但在post请求时出现了问题。 先来看一下post请求的代码实例 跟踪代码发现  查了一下MultiValueMap的说明发现了此问

    2024年02月12日
    浏览(10)
  • windows部署es6.8.0集群并部署到spring boot

    windows部署es6.8.0集群并部署到spring boot

    1、先下载windows版本es 2、下载完成之后,建一个文件夹elasticsearch-cluster,把es解压到里边,并且在复制两份 3、去 conf 文件夹下,打开 elasticsearch.yml 文件添加以下配置 ,分别是三个es的 elasticsearch.yml 文件的配置 cluster.name: my-application node.name: node-1 network.host: 127.0.0.1 http.port: 9

    2023年04月21日
    浏览(9)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包