首页 > 其他分享 >Spring Boot 2.x基础教程:使用Elastic Job实现定时任务

Spring Boot 2.x基础教程:使用Elastic Job实现定时任务

时间:2022-10-06 16:36:34浏览次数:84  
标签:INFO 15 07 Elastic Spring Boot --- job 20

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

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

Elastic 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更方便呢?

标签:INFO,15,07,Elastic,Spring,Boot,---,job,20
From: https://www.cnblogs.com/jieran/p/16757841.html

相关文章

  • Spring-MVC原理
        DispactherServletDispactherServlet为整个SpringMVC的控制中心,用于接收拦截用于的请求原理1.浏览器向服务器发送请求,DispactherServlet拦截请求并调用处......
  • Spring Boot 2.x基础教程:使用@Scheduled实现定时任务
    我们在编写SpringBoot应用中经常会遇到这样的场景,比如:我需要定时地发送一些短信、邮件之类的操作,也可能会定时地检查和监控一些标志、参数等。创建定时任务在SpringBoo......
  • SpringMVC之内容协商策略
    内容协商原理目录内容协商原理一、引言二、正常请求请求数据格式确定和返回值数据格式确定三、内容协商确定客户端接收数据格式默认基于请求头确定请求数据格式确定服务端......
  • Elasticsearch 进阶检索 (一)
    1、官方文档https://www.elastic.co/guide/en/elasticsearch/reference/7.4/index.htmlSearchAPIES支持两种基本方式检索:一个是通过使用RESTrequestURL发送搜索......
  • Spring中最常用的11个扩展点
    转载自:微信公众号[Java后端技术]前言我们一说到spring,可能第一个想到的是IOC(控制反转)和AOP(面向切面编程)。没错,它们是spring的基石,得益于它们的优秀设计,使得sprin......
  • SpringAOP之通过注解方式实现
    通过注解的方式1)导入jar包<!--Spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.1.3.Release</ve......
  • springboot 项目启动后访问不论什么请求的是spring的注册页面Please sign in Username
    解决方法:1.在启动类上添加注解@EnableAutoConfiguration(exclude={SecurityAutoConfiguration.class})2.或者:@SpringBootApplication(exclude={SecurityAutoConfigu......
  • SpringBoot整合Websocket
    1.什么是WebSocket1.HTTP协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理,HTTP协议无法......
  • Spring Boot 自动装配原理初解
    原理初探pom.xmlspring-boot-dependencies:核心以来在父工程中!我们在写或者引入一些Springboot依赖的时候,不需要指定版本,就因为有这些版本仓库启动器-<depende......
  • Elasticsearch 初步检索
    1丶_catGET/_cat/nodes:查看所有节点GET/_cat/health:查看es健康状况GET/_cat/master:查看主节点GET/_cat/indices:查看所有索引相当于showdatabase查......