Spring Cloud Alibaba 集成分布式定时任务调度功能
作者:千习
背景简介
定时任务是指在约定的时间,或者按照固定频率周期性执行的任务。在企业应用中,非用户行为发起的后台业务,一般都是通过定时任务来实现,常见场景如下:
- 异步数据处理:比如先将订单入库,每分钟扫描未支付的订单做批处理。
- 自动化运维:比如每小时清理一次数据库的历史记录。
- 系统监控:比如每分钟扫描监控指标,如果超出阈值,进行报警。
- 数据同步:比如每天凌晨 1 点把 mysql 中的数据同步到大数据平台中。
在单体应用中,实现定时任务很简单,比如 Java 中有 java.util.Timer 和 ScheduledExecutorService。在 Spring 框架中也提供了 scheduling 方便的开发定时任务。但是在微服务中,一个应用一般来说有很多节点,通过以上实现方式,就会带来一个致命的问题,那就是任务重复执行。

Spring Cloud Alibaba 发布了 Scheduling 任务调度 [ 1] 模块 [#3732] [ 2] 提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
微服务下的分布式任务能力
定时任务功能作为应用开发中重要能力之一,在 Spring Framework [ 3] 中提供了对定时任务支持,在其最基础的使用场景下可方便的通过 @Scheduled 注解轻松的开发出一个定时任务【剖析参考 [ 4] 】;也可以通过扩展集成 Quartz 框架来实现部分分布式能力,但其目前无法方便的通过 spring 的 @Scheduled 注解快速地定义一个任务。框架原生提供的这些能力在单体应用场景下够用,但在微服务分布式集群场景下就显得有些力所不能及了。
因此在 Spring Cloud Alibaba 体系中我们希望提供一个模块能力,能在微服务场景下快速接入使用分布式定时任务能力。分布式定时任务应该具备哪些能力特性,参考如下对比。

在微服务分布式场景中,除了基础的定时任务运行能力,还需提供如:防重复执行、分片运行、任务执行并行度控制等能力,后续还可在此基础上继续探索定时任务对微服务应用服务本身的定时调度支持,欢迎在社区提出需求和建议。
快速接入体验
在新版的 Spring Cloud Alibaba 版本中提供分布式任务调度快速启动模块 spring-cloud-starter-alibaba-schedulerx 来支持各类分布式定时任务方案集成。对于采用了 Spring Cloud Alibaba 的微服务应用可以通过添加如下 pom 依赖完成接入。
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-schedulerx</artifactId><version>{version}</version>
</dependency>
在应用配置文件提供了 spring.cloud.scheduling.distributed-mode 参数让用户选择采用哪一种实现方案,目前提供了基于“阿里云 schedulerx”和“开源 shedlock”两种模式。后续可根据社区用户需求继续增加其他方案的接入。更为具体详细的接入说明可参考:Example 示例工程 [ 5] 。
采用阿里云 SchedulerX
接入 Spring 分布式定时任务,最简单的方式就是直接接入阿里云托管的分布式任务调度平台 SchedulerX [ 6] ,不但完全兼容 Spring @Scheduled 注解,还具有高可用、高安全、高性能、免运维、低成本等特点。
任务调度平台 SchedulerX 的任务管理平台,可以帮助您动态新增、修改、运维定时任务,还有报警监控、历史记录、日志服务、链路追踪等企业级可观测方案,同时还可获得如任务分片执行等增强能力,为应用线上定时任务稳定运行保驾护航。

接入步骤
-
登录 SchedulerX 控制台 [ 7] ,免费开通服务。
-
参考接入文档 [ 8] 接入,每个账号拥有 5 个免费任务额度,可先 0 成本试用体验。

采用本地开源方式
不借助云产品,本地接入方式可以再结合 @SchedulerLock [ 9] 注解来实现分布式定时任务。
@SchedulerLock 注解是一个分布式锁的框架,结合 @Scheduled 注解,可以保证任务同一时间,在多个节点上只会执行一次。该框架支持多种分布式锁的实现,比如 Jdbc、Zookeeper、Redis 等,目前的集成模块中只提供了 Jdbc 的方案,后续会继续新增其他模式来满足用户现有场景架构所需。其原理如下:

接入步骤
下面以 Mysql 分布式锁为例,演示分布式任务的接入过程,首先需要按本章节开始说明添加 spring-cloud-starter-alibaba-schedulerx 和对应配置参数,除此之外用户还需完成如下配置:
- 由于采用 jdbc 作为分布式锁实现,因此还需如下 pom 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>
- 在 application.properties 文件中添加 jdbc 配置(如果已经添加可以忽略这步)
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class=com.mysql.cj.jdbc.Driver
完成上述配置启动应用后,会在对应数据库中创建一个 shedlock 表用于定时任务的执行同步处理。
应用程序代码及任务示例参考如下:
配置启动类,启用 SchedulingTasks:
@SpringBootApplication
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "3m")
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
创建定时任务:
import org.joda.time.DateTime;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;@Component
public class SpringJob {/*** 每5分钟跑一次*/@Scheduled(cron = "0 */5 * * * ?")@SchedulerLock(name = "SpringJob.job1", lockAtMostFor = "2m", lockAtLeastFor = "1m")public void job1() {System.out.println("time=" + DateTime.now().toString("YYYY-MM-dd HH:mm:ss") + " do job1...");}/*** 每5秒跑一次*/@Scheduled(fixedRate = 5000)@SchedulerLock(name = "SpringJob.job2", lockAtMostFor = "4s", lockAtLeastFor = "4s")public void job2() {System.out.println("time=" + DateTime.now().toString("YYYY-MM-dd HH:mm:ss") + " do job2...");}/*** 上次跑完之后隔5秒再跑* @throws InterruptedException */@Scheduled(fixedDelay = 5000)@SchedulerLock(name = "SpringJob.job3", lockAtMostFor = "4s", lockAtLeastFor = "4s")public void job3() throws InterruptedException {System.out.println("time=" + DateTime.now().toString("YYYY-MM-dd HH:mm:ss") + " do job3...");Thread.sleep(10000);}
}
未来规划
Spring Cloud Alibaba 分布式定时调度模块为微服务应用场景提供了快速集成接入解决方案,后续可为更多分布式定时任务实现方案提供快速集成,比如:继续集成 quartz/xxljob 等开源组件,且让上述开源组件也都能来适配 spring 的 @Scheduled 注解,实现一份任务代码可对接不同调度服务;同时也会为分布式任务场景下所需的业务能力提供扩展支持。欢迎大家给开源社区 [ 10] 提出关于分布式定时任务的业务功能诉求和建议。
相关链接:
[1] Scheduling 任务调度
https://sca.aliyun.com/docs/2023/user-guide/schedulerx/quick-start/
[2] [#3732]
https://github.com/alibaba/spring-cloud-alibaba/pull/3732
[3] Spring Framework
https://docs.spring.io/spring-framework/docs/5.3.37/reference/html/integration.html#scheduling
[4] 剖析参考
https://developer.aliyun.com/article/1015756
[5] Example 示例工程
https://github.com/alibaba/spring-cloud-alibaba/blob/2023.x/spring-cloud-alibaba-examples/spring-cloud-scheduling-example/README.md
[6] 分布式任务调度平台 SchedulerX
https://www.aliyun.com/ntms/middleware/schedulerx
[7] SchedulerX 控制台
https://schedulerx2.console.aliyun.com/public/AppList
[8] 接入文档
https://help.aliyun.com/zh/schedulerx/user-guide/spring-jobs?spm=5176.14256785.help.dexternal.f09e126dAXAvEs#p-9sy-0ay-hgx
[9] @SchedulerLock
https://github.com/lukas-krecan/ShedLock
[10] 开源社区
https://sca.aliyun.com/
相关文章:
Spring Cloud Alibaba 集成分布式定时任务调度功能
作者:千习 背景简介 定时任务是指在约定的时间,或者按照固定频率周期性执行的任务。在企业应用中,非用户行为发起的后台业务,一般都是通过定时任务来实现,常见场景如下: 异步数据处理:比如先…...
中职云计算实训室
一、实训室建设背景 随着信息技术的飞速发展,云计算已成为推动数字化转型、促进经济社会发展的重要力量。《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》明确提出,要加快数字化发展,建设数字中国。云计算作为数…...
【python制作一个小程序作为七夕礼物】
制作一个七夕节礼物的小程序,我们可以考虑一个简单的互动程序,比如一个“七夕情侣姓名配对指数计算器”。这个程序将接收两个名字作为输入,然后输出一个随机的“配对指数”和一些浪漫的话语。以下是一个使用Python实现的简单示例:…...
一篇文章教会你如何使用Haproxy,内含大量实战案例
1. Haproxy 介绍 HAProxy是法国开发者 威利塔罗(Willy Tarreau) 使用C语言编写的自由及开放源代码软件,是一款具备高并发(万级以上)、高性能的TCP和HTTP应用程序代理. HAProxy运行在当前的硬件上,可以支持…...
PythonStudio 控件使用常用方式(二十二)TFlowPanel
PythonStudio是一个极强的开发Python的IDE工具,官网地址是:https://glsite.com/ ,在官网可以下载最新版的PythonStudio,同时,在使用PythonStudio时,它也能及时为用户升到最新版本。它使用的是Delphi的控件&…...
培训第二十七天(lvs_nat模式与lvs_dr模式配置)
上午 核心:内核中的ipvs,ipvsadm1、安装ipvsadm[rootnat ~]# yum -y install ipvsadm2、配置规则查看所有的规则,如果已经配置好规则,重启之后也就没有了[rootnat ~]# ipvsadm -L -n 1、配置vip网卡 (1)在…...
JAVA中DateFormat详解
在Java中,DateFormat 是一个抽象类,它用于格式化和解析日期。DateFormat 允许进行日期-文本之间的转换,以及日期-时间之间的解析和格式化。Java 提供了多个 DateFormat 的具体子类,其中最常用的是 SimpleDateFormat,它…...
uniapp——列表选择样式
案例 代码 <view class"list"><block v-for"(item,index) in 8" :key"index"><view class"item" click"choosePackage(item)" :class"{active:item current}"><view class"i_money&q…...
解决客户访问超时1s问题
访问公网地址返回状态码499-CSDN博客 需求描述 客户访问公司公网服务,期望在1s内完成。他们在客户端设置了超时1s的配置,如果超过1s公司服务就会报错499,这是正常的请求返回。 这里是业务简易的连路图: 分析问题 目前这个服务通过公网的alb负载均衡到ecs,通过ecs再转发…...
Linux命令(基础面试可用,都是自己觉得平时使用多的)
1.cat 参数:-n:显示行号-s:压缩连续的空行,只显示一个空行2.chattr 改变文件属性 语法:chattr [-RV] [/-/<属性>][文件或目录] 属性:a:让文件或目录仅供附加用途i:不得任意更…...
opencv-python图像增强一:传统图像去噪方法整理
一、简介: 在数字图像处理领域,噪声一直是影响图像质量的重要因素。无论是拍摄过程中的环境干扰,还是传输过程中的信号失真,噪声都可能导致图像模糊、细节丢失,甚至影响后续的图像分析和应用。为了提高图像的视觉效果…...
Canal单机部署
目录 一、前期准备 1、配置binlog日志 2、配置MQ服务 二、搭建canal 1、下载安装包 2、部署canal-admin的UI管理界面 2-1、创建&解压admin 2-2、配置UI管理界面 2-3、初始化元数据库 2-4、启动Canal Admin 3、部署canal-server服务 3-1、创建&解压deployer…...
java,每日练习02
题目 选自牛客网 1.下列关于Java中类的构造方法的描述,正确的是() A.构造方法的返回类型为void B.可以定义一个类而在代码中不写构造方法。 C.在同一个类中定义的重载构造方法不可以相互调用。 D.子类不允许调用父类的构造方法。 正确答案…...
C# TreeView
添加 TreeView 控件:定义节点:添加节点:设置节点属性:处理节点事件:自定义节点绘制:数据绑定:节点选择:节点展开和折叠:搜索和过滤:示例代码总结 C# 中的 Tre…...
通过xshell使用密钥连接阿里云服务器
目录 步骤1:创建密钥对 步骤2:连接服务器 步骤3:连接服务器 连接阿里云服务器有几种方式,例如有密码进行连接,但是密码连接安全风险较大,所以我们选择密钥方式进行连接。操作简单且安全性高 步骤1&…...
<数据集>路面坑洼识别数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:681张 标注数量(xml文件个数):681 标注数量(txt文件个数):681 标注类别数:1 标注类别名称:[pothole] 使用标注工具:labelImg 标注规则:对类…...
几个常用脚本
系统初始化 #!/bin/bash # 定义颜色常量 RED\033[0;31m GREEN\033[0;32m NC\033[0m # No Color #功能菜单 menu() {clearecho "请选择要执行的操作:"echo "1. 检查网络"echo "2. 关闭防火墙和SELinux"echo "3. 替换YUM源"echo "…...
gtest中TEST和TEST_F和TEST_P的区别是什么
gtest(Google Test)是Google开发的一个开源的C测试框架,它提供了多种宏来支持不同类型的测试。其中,TEST、TEST_F和TEST_P是三个常用的宏,它们各自有不同的用途和特性。以下是它们之间的主要区别: TEST 用…...
VS2022如何调出输出窗口,并在输出窗口打印日志
在输出窗口打印 System.Diagnostics.Debug.WriteLine("这是一行自定义的输出。Debug.WriteLine");System.Diagnostics.Debug.Write("这是第二行自定义的输出,Debug.Write");System.Diagnostics.Debug.WriteLine("换行");System.Diagn…...
【全国大学生电子设计竞赛】2021年I题
🥰🥰全国大学生电子设计大赛学习资料专栏已开启,限时免费,速速收藏~...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
