文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringCloud—集成分布式任务调度平台

2024-12-13 21:58

关注

定时任务几乎是每个业务系统必不可少的功能,计算到期时间、过期时间等,定时触发某项任务操作。在使用单体应用时,基本使用Spring提供的注解即可实现定时任务,而在使用微服务集群时,这种方式就要考虑添加分布式锁来防止多个微服务同时运行定时任务而导致同一个任务重复执行。

除了使用注解,现在还有一种方式,就是搭建分布式任务平台,所有的微服务注册到分布式任务平台,由分布式任务平台统一调度,这样避免了同一任务被重复执行。这里我们选择使用XXL-JOB作为分布式任务调度平台,XXL-JOB核心设计目标是开发迅速、学习简单、轻量级、易扩展。

使用分布式任务调度平台的优点除了避免同一任务重复执行外,还有使用简单,可以手动执行、有详细的调度日志查看任务具体执行情况等优点。XXL-JOB官方架构设计图:

下面我们按照步骤来介绍,如何结合我们的微服务平台将分布式任务调度平台XXL-JOB集成进来,实现我们需要的定时任务功能。

一、微服务框架整合xxl-job-admin

1、XXL-JOB开源网站下载源码,下载地址https://github.com/xuxueli/xxl-job/releases,下载下来的源码如下:

xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
:xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;
:xxl-job-executor-sample-frameless:无框架版本;

下载下来的开源包有三个目录:xxl-job-admin、xxl-job-core和xxl-job-executor-samples,顾名思义,xxl-job-admin是分布式任务平台的服务端兼管理台,我们需要部署的也是这个工程,我们可以把整个工程集成到我们的微服务中,统一打包部署;xxl-job-core是公共依赖包,我们其他需要实现定时任务的微服务需要引入这个包来实现定时任务执行器。xxl-job-executor-samples为定时任务执行器的实例代码。

2、在基础平台gitegg-platform工程gitegg-platform-bom中引入xxl-job-core核心包,统一版本管理。

......

<xxl-job.version>2.3.1xxl-job.version>
......

<dependency>
<groupId>com.xuxueligroupId>
<artifactId>xxl-job-coreartifactId>
<version>${xxl-job.version}version>
dependency>

3、将xxl-job-admin集成到微服务工程中,方便统一打包部署

根据我们的微服务架构设计,gitegg-plugin作为我们系统的插件工程,里面放置我们需要的插件服务。有些插件是必须的,而有些插件可能会用不到,此时我们就可以根据自己的业务需求去选择部署业务插件。为和我们的微服务深度集成就不是解耦的特性,我们需要对xxl-job-admin的配置文件进行适当的修改:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>gitegg-pluginartifactId>
<groupId>com.gitegg.cloudgroupId>
<version>1.0.1.RELEASEversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>gitegg-jobartifactId>
<name>${project.artifactId}name>
<packaging>jarpackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8maven.compiler.encoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<maven.test.skip>truemaven.test.skip>
<netty-all.version>4.1.63.Finalnetty-all.version>
<gson.version>2.9.0gson.version>
<spring.version>5.3.20spring.version>
<spring-boot.version>2.6.7spring-boot.version>
<mybatis-spring-boot-starter.version>2.2.2mybatis-spring-boot-starter.version>
<mysql-connector-java.version>8.0.29mysql-connector-java.version>
<slf4j-api.version>1.7.36slf4j-api.version>
<junit-jupiter.version>5.8.2junit-jupiter.version>
<javax.annotation-api.version>1.3.2javax.annotation-api.version>
<groovy.version>3.0.10groovy.version>
<maven-source-plugin.version>3.2.1maven-source-plugin.version>
<maven-javadoc-plugin.version>3.4.0maven-javadoc-plugin.version>
<maven-gpg-plugin.version>3.0.1maven-gpg-plugin.version>
properties>
<dependencies>

<dependency>
<groupId>com.gitegg.platformgroupId>
<artifactId>gitegg-platform-bootartifactId>
dependency>

<dependency>
<groupId>com.gitegg.platformgroupId>
<artifactId>gitegg-platform-cloudartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>${mybatis-spring-boot-starter.version}version>

<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>

<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
exclusion>
exclusions>
dependency>

<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-freemarkerartifactId>

<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
exclusion>
exclusions>
dependency>

<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>

<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
exclusion>
exclusions>
dependency>

<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>

<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
exclusion>
exclusions>
dependency>

<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql-connector-java.version}version>
dependency>

<dependency>
<groupId>com.xuxueligroupId>
<artifactId>xxl-job-coreartifactId>

<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
exclusion>
exclusions>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>com.google.cloud.toolsgroupId>
<artifactId>jib-maven-pluginartifactId>
plugin>
plugins>
build>

project>

bootstrap.yml配置:

server:
port: 8007
spring:
profiles:
active: '@spring.profiles.active@'
application:
name: '@artifactId@'
cloud:
inetutils:
ignored-interfaces: docker0
nacos:
discovery:
server-addr: ${spring.nacos.addr}
config:
server-addr: ${spring.nacos.addr}
file-extension: yaml
extension-configs:
# 必须带文件扩展名,此时 file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响
- data-id: ${spring.nacos.config.prefix}.yaml
group: ${spring.nacos.config.group}
refresh: true
- data-id: ${spring.nacos.config.prefix}-xxl-job.yaml
group: ${spring.nacos.config.group}
refresh: true
### xxl-job-admin config
mvc:
servlet:
load-on-startup: 0
static-path-pattern: /static*.jksinclude>
<include>static*.xmlinclude>
includes>
resource>
resources>

6、在Gateway添加xxl-job-admin路由转发

xxl-job-admin路由转发需要添加两方面内容,一个是xxl-job-admin注册到Nacos注册中心上的gitegg-job服务,一个是xxl-job-admin前端页面请求的静态文件转发。第一个是为了和我们整体微服务保持一致,第二个是为了解决xxl-job-admin前端ftl页面在请求静态文件时,请求的是/xxl-job-admin根路径。新增Gateway路由转发配置如下:

- id: gitegg-job
uri: lb://gitegg-job
predicates:
- Path=/gitegg-job
@Slf4j
@Configuration
public class XxlJobConfig {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
log.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}

}

Nacos配置中心:

xxl:
job:
admin:
addresses: http://127.0.0.1/xxl-job-admin
accessToken: 'default_token'
executor:
appname: ${spring.application.name}
address:
ip:
port: 9999
logpath: D:\\log4j2_nacos\\xxl-job\\jobhandler
logretentiondays: 30

2、实现定时任务测试代码

我们在gitegg-service-system中测试定时任务执行器,先在pom.xml中添加gitegg-platform-xxl-job依赖,然后新增SystemJobHandler.java测试类。

SystemJobHandler.java:

package com.gitegg.service.system.jobhandler;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class SystemJobHandler {

@XxlJob("systemJobHandler")
public void systemJobHandler() throws Exception {

XxlJobHelper.log("不带返回值:XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
}

@XxlJob("userJobHandler")
public ReturnT<String> userJobHandler() throws Exception {
XxlJobHelper.log("带返回值:XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
return ReturnT.SUCCESS;
}

}

3、配置xxl-job-admin新增执行器

4、新增xxl-job-admin任务

执行器可以看做是一组微服务,而任务是微服务具体执行的方法。任务新增后,默认是STOP状态,需要手动启动,当列表显示RUNNING时,表示该任务是运行状态,会根据配置的时间执行。

5、查看执行器是否执行

在本地开发环境查看任务执行的方式有多种,直接Debug也可以,生产环境我们可以查看xxl-job日志,在测试代码中记录的log,在xxl-job-admin管理台都可以详细查看。

通过以上操作步骤,我们将xxl-job和xxl-job-admin整合到了我们的微服务架构中,只需要在有任务调度需求的微服务中实现执行器就可以满足我们的需求了。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯