上一篇,我们介绍了如何使用Spring Boot自带的@Scheduled注解实现定时任务。文末也提及了这种方式的局限性。当在集群环境下的时候,如果任务的执行或操作依赖一些共享资源的话,就会存在竞争关系。如果不引入分布式锁等机制来做调度的话,就可能出现预料之外的执行结果。所以,@Scheduled注解更偏向于使用在单实例自身维护相关的一些定时任务上会更为合理一些,比如:定时清理服务实例某个目录下的文件、定时上传本实例的一些统计数据等。

那么,在实际实现业务逻辑的时候,没有更好的定时任务方案呢?今天我们就来介绍一个老牌的分布式定时任务框架,在Spring Boot下的使用案例。

Elasitc Job

Elastic Job的前生是当当开源的一款分布式任务调度框架,而目前已经加入到了Apache基金会。

该项目下有两个分支:ElasticJob-Lite和ElasticJob-Cloud。ElasticJob-Lite是一个轻量级的任务管理方案,本文接下来的案例就用这个来实现。而

ElasticJob-Cloud则相对重一些,因为它使用容器来管理任务和隔离资源。

更多关于ElasticJob的介绍,您也可以点击这里直达官方网站了解更多信息。

动手试试

说那么多,一起动手试试吧!

第一步:创建一个最基础的Spring Boot项目,如果还不会?那么看看这篇快速入门

第二步pom.xml中添加elasticjob-lite的starter

<dependencies>
<dependency>
<groupId>org.apache.shardingsphere.elasticjob</groupId>
<artifactId>elasticjob-lite-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency> // ...
</dependencies>

第三步:创建一个简单任务

@Slf4j
@Service
public class MySimpleJob implements SimpleJob { @Override
public void execute(ShardingContext context) {
log.info("MySimpleJob start : didispace.com {}", System.currentTimeMillis());
} }

第四步:编辑配置文件

elasticjob.reg-center.server-lists=localhost:2181
elasticjob.reg-center.namespace=didispace elasticjob.jobs.my-simple-job.elastic-job-class=com.didispace.chapter72.MySimpleJob
elasticjob.jobs.my-simple-job.cron=0/5 * * * * ?
elasticjob.jobs.my-simple-job.sharding-total-count=1

这里主要有两个部分:

第一部分:elasticjob.reg-center开头的,主要配置elastic job的注册中心和namespace

第二部分:任务配置,以elasticjob.jobs开头,这里的my-simple-job是任务的名称,根据你的喜好命名即可,但不要重复。任务的下的配置elastic-job-class是任务的实现类,cron是执行规则表达式,sharding-total-count是任务分片的总数。我们可以通过这个参数来把任务切分,实现并行处理。这里先设置为1,后面我们另外讲分片的使用。

运行与测试

完成了上面所有操作时候,我们可以尝试运行一下上面应用,因为这里需要用到ZooKeeper来协调分布式环境下的任务调度。所以,你需要先在本地安装ZooKeeper,然后启动它。注意:上面elasticjob.reg-center.server-lists配置,根据你实际使用的ZooKeeper地址和端口做相应修改。

在启动上述Spring Boot应用之后,我们可以看到如下日志输出:

2021-07-20 15:33:39.541  INFO 56365 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'my-simple-job' initialized from an externally provided properties instance.
2021-07-20 15:33:39.541 INFO 56365 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler version: 2.3.2
2021-07-20 15:33:39.551 INFO 56365 --- [ main] org.apache.curator.utils.Compatibility : Using org.apache.zookeeper.server.quorum.MultipleAddresses
2021-07-20 15:33:40.067 INFO 56365 --- [ main] c.d.chapter72.Chapter72Application : Started Chapter72Application in 3.25 seconds (JVM running for 4.965)
2021-07-20 15:33:40.069 INFO 56365 --- [ main] .s.b.j.ScheduleJobBootstrapStartupRunner : Starting ElasticJob Bootstrap.
2021-07-20 15:33:40.078 INFO 56365 --- [ main] org.quartz.core.QuartzScheduler : Scheduler my-simple-job_$_NON_CLUSTERED started.
2021-07-20 15:33:40.078 INFO 56365 --- [ main] .s.b.j.ScheduleJobBootstrapStartupRunner : ElasticJob Bootstrap started.
2021-07-20 15:33:45.157 INFO 56365 --- [le-job_Worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : didispace.com 1626766425157
2021-07-20 15:33:50.010 INFO 56365 --- [le-job_Worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : didispace.com 1626766430010
2021-07-20 15:33:55.013 INFO 56365 --- [le-job_Worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : didispace.com 1626766435013

既然是分布式任务调度,那么我们再启动一个(注意,在同一台机器启动的时候,会端口冲突,可以在启动命令中加入-Dserver.port=8081来区分端口),在第二个启动的服务日志也打印了类似的内容

2021-07-20 15:34:06.430  INFO 56371 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'my-simple-job' initialized from an externally provided properties instance.
2021-07-20 15:34:06.430 INFO 56371 --- [ main] org.quartz.impl.StdSchedulerFactory : Quartz scheduler version: 2.3.2
2021-07-20 15:34:06.436 INFO 56371 --- [ main] org.apache.curator.utils.Compatibility : Using org.apache.zookeeper.server.quorum.MultipleAddresses
2021-07-20 15:34:06.786 INFO 56371 --- [ main] c.d.chapter72.Chapter72Application : Started Chapter72Application in 1.446 seconds (JVM running for 1.884)
2021-07-20 15:34:06.787 INFO 56371 --- [ main] .s.b.j.ScheduleJobBootstrapStartupRunner : Starting ElasticJob Bootstrap.
2021-07-20 15:34:06.792 INFO 56371 --- [ main] org.quartz.core.QuartzScheduler : Scheduler my-simple-job_$_NON_CLUSTERED started.
2021-07-20 15:34:06.792 INFO 56371 --- [ main] .s.b.j.ScheduleJobBootstrapStartupRunner : ElasticJob Bootstrap started.
2021-07-20 15:34:10.182 INFO 56371 --- [le-job_Worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : didispace.com 1626766450182
2021-07-20 15:34:15.010 INFO 56371 --- [le-job_Worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : didispace.com 1626766455010
2021-07-20 15:34:20.013 INFO 56371 --- [le-job_Worker-1] com.didispace.chapter72.MySimpleJob : MySimpleJob start : didispace.com 1626766460013

此时,在回头看看之前第一个启动的应用,日志输出停止了。由于我们设置了分片总数为1,所以这个任务启动之后,只会有一个实例接管执行。这样就避免了多个进行同时重复的执行相同逻辑而产生问题的情况。同时,这样也支持了任务执行的高可用。比如:可以尝试把第二个启动的应用(正在打印日志的)终止掉。可以发现,第一个启动的应用(之前已经停止输出日志)继续开始打印任务日志了。

在整个实现过程中,我们并没有自己手工的去编写任何的分布式锁等代码去实现任务调度逻辑,只需要关注任务逻辑本身,然后通过配置分片的方式来控制任务的分割,就可以轻松的实现分布式集群环境下的定时任务管理了。是不是在复杂场景下,这种方式实现起来要比@Scheduled更方便呢?

记得自己动手写一写,这样体会更深哦!如果碰到问题,可以拉取文末的代码示例对比一下是否有地方配置不一样。下一篇,我们还将继续介绍关于定时任务的一些高级内容。如果您对这个内容感兴趣,可以收藏本系列教程《Spring Boot 2.x基础教程》点击直达!。学习过程中如遇困难,可以加入我们的Spring技术交流群,参与交流与讨论,更好的学习与进步!

代码示例

本文的完整工程可以查看下面仓库中的chapter7-2目录:

如果您觉得本文不错,欢迎Star支持,您的关注是我坚持的动力!

欢迎关注我的公众号:程序猿DD,分享外面看不到的干货与思考!

Spring Boot 2.x基础教程:使用Elastic Job实现定时任务的更多相关文章

  1. Spring Boot 2.x基础教程:使用@Scheduled实现定时任务

    我们在编写Spring Boot应用中经常会遇到这样的场景,比如:我需要定时地发送一些短信.邮件之类的操作,也可能会定时地检查和监控一些标志.参数等. 创建定时任务 在Spring Boot中编写定时 ...

  2. Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档

    随着前后端分离架构和微服务架构的流行,我们使用Spring Boot来构建RESTful API项目的场景越来越多.通常我们的一个RESTful API就有可能要服务于多个不同的开发人员或开发团队:I ...

  3. Spring Boot 2.x基础教程:JSR-303实现请求参数校验

    请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...

  4. Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解

    之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档 ...

  5. Spring Boot 2.x基础教程:Swagger静态文档的生成

    前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...

  6. Spring Boot 2.x基础教程:使用国产数据库连接池Druid

    上一节,我们介绍了Spring Boot在JDBC模块中自动化配置使用的默认数据源HikariCP.接下来这一节,我们将介绍另外一个被广泛应用的开源数据源:Druid. Druid是由阿里巴巴数据库事 ...

  7. Spring Boot 2.x基础教程:找回启动日志中的请求路径列表

    如果您看过之前的Spring Boot 1.x教程,或者自己原本就对Spring Boot有一些经验,或者对Spring MVC很熟悉.那么对于Spring构建的Web应用在启动的时候,都会输出当前应 ...

  8. Spring Boot 2.x基础教程:使用MyBatis的XML配置方式

    上一篇我们介绍了如何在Spring Boot中整合我们国人最常用的MyBatis来实现对关系型数据库的访问.但是上一篇中使用了注解方式来实现,而对于很多MyBatis老用户还是习惯于XML的开发方式, ...

  9. Spring Boot 2.x基础教程:Spring Data JPA的多数据源配置

    上一篇我们介绍了在使用JdbcTemplate来做数据访问时候的多数据源配置实现.接下来我们继续学习如何在使用Spring Data JPA的时候,完成多数据源的配置和使用. 添加多数据源的配置 先在 ...

随机推荐

  1. GPU 硬件虚拟化Hardware Virtualization

    GPU 硬件虚拟化Hardware Virtualization 1. Principles 一个物理GPU可以虚拟化为多个vGPUs.VMs可以绑定到vGPUs以直接访问一些物理GPU资源. 2. ...

  2. SLAM的通用框架:GSLAM

    SLAM的通用框架:GSLAM GSLAM: A General SLAM Framework and Benchmark 论文链接: http://openaccess.thecvf.com/con ...

  3. ffmpeg architecture(下)

    ffmpeg architecture(下) 第3章-转码 TLDR:给我看代码和执行. $ make run_transcoding 我们将跳过一些细节,但是请放心:源代码可在github上找到. ...

  4. Nucleus-SE迁移:未实现的设施和兼容性

    Nucleus-SE迁移:未实现的设施和兼容性 Nucleus SE migration: Unimplemented facilities and compatibility Nucleus SE的 ...

  5. postman环境变量配置的详细过程(步骤加截图)

    环境变量的配置 实战:https://www.baidu.com/s?wd=博客园 使用cmd命令模式输入代码:Nslookup www.baidu.com 模拟环境:线上环境14.215.177.3 ...

  6. 分布式Jmeter压测机的部署

    部署 1.分布式配置 Master机Jmeter安装目录下/bin/jmeter.properties remote_hosts修改为slave压力机的IP 如 remote_hosts=10.0.4 ...

  7. 性能工具之stress工具使用教程(带源码说明)

      stress是一个在linux下的压力测试小工具. 我看到有些人用这个工具来描述一些资源耗尽的场景,也有人用它来做混沌测试中.请使用者要注意,这个工具并不是模拟业务问题的,是模拟系统级问题的.所以 ...

  8. 【NX二次开发】获取对象边界包容盒的三个函数UF_MODL_ask_bounding_box

    今天看到胡工对bounding_box的分享,我也来测试一番(原帖地址:https://www.ugapi.com/thread-10287.html) 获取对象的边界盒子的三个函数: 1 UF_MO ...

  9. python学习笔记03-变量和字符串

    变量 变量:把一个值赋值给一个名字时,它会储存在内存中,称之为变量(virable):但在python中并不会储存在变量里,仅仅是类似于给值加了标签 变量的使用规则: 1.使用变量,首先需要给变量赋值 ...

  10. 消息队列面试题、RabbitMQ面试题、Kafka面试题、RocketMQ面试题 (史上最全、持续更新、吐血推荐)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...