集群部署项目时,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项目后, 有以下问题: ① 右键没有Run ② 右键New新建文件发现无Java Class选项 然后解决掉 ①② 问题后出现新的问题: ③ @SpringBootApplication 注解爆红找不到引用 ④ pom依赖能下载但是加

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    2024年02月12日
    浏览(52)
  • 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日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包