关于java:Spring-Boot-2x基础教程使用Elastic-Job实现定时任务

5次阅读

共计 5042 个字符,预计需要花费 13 分钟才能阅读完成。

上一篇,咱们介绍了如何应用 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 目录:

  • Github:https://github.com/dyc87112/SpringBoot-Learning/
  • Gitee:https://gitee.com/didispace/SpringBoot-Learning/

如果您感觉本文不错,欢送 Star 反对,您的关注是我保持的能源!

欢送关注我的公众号:程序猿 DD,分享其余中央看不到的常识与思考

正文完
 0