当前位置:首页 > 后端开发 > 正文内容

xxl-job,使命调度中心快速上手

邻居的猫1个月前 (12-09)后端开发1111

前语

XXL-JOB是一个能够在WEB界面装备履行守时使命中间件,支撑分布式服务调用,XXL-JOB自身也能够布置多个节点组成集群,自身是一个依据SpringBoot的Java WEB程序,咱们能够经过下载GitHub源码进行布置。

一、XXL-JOB 装置教程

进入 xxl-job官网,里边有更具体的教程 XXL-JOB官网

1、下载源码
git clone http://gitee.com/xuxueli0323/xxl-job

经过IDEA翻开后目录如下:

2、初始化"调度数据库"

“调度数据库初始化SQL脚本” 方位为:

`/xxl-job/doc/db/tables_xxl_job.sql`

没错,你得履行这个sql文件到你的数据库中,履行完后 会有如下库和表出现在数据库中

3、项目结构
  1. xxl-job-admin:调度中心
  2. xxl-job-core:公共依靠
  3. xxl-job-executor-samples:履行器Sample示例(挑选适宜的版别履行器,可直接运用,也能够参阅其并将现有项目改形成履行器)
    1. :xxl-job-executor-sample-springboot:Springboot版别,经过Springboot办理履行器,本文章以这种方法介绍,官方引荐该方法;
    2. :xxl-job-executor-sample-frameless:无结构版别;
好了~,到这一步你的XXL—JOB算是装好了,下一步让咱们来发动它

二、发动调度中心前的预备

  1. 调度中心项目:xxl-job-admin 《超要害,起的便是这玩意儿》
  2. 效果:统一办理使命调度渠道上调度使命,担任触发调度履行,而且供给使命办理渠道。

先修正一下调度中心xxl-job-admin的装备文件。

`/xxl-job/xxl-job-admin/src/main/resources/application.properties`

首要修正数据库为自己的方才履行sql的库

### xxl-job, datasource
spring.datasource.url=jdbc:mysql://123.45.678.90:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=xxx用户
spring.datasource.password=xxx暗码
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

然后发动项目

`xxl-job-admin/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.java`

调度中心拜访地址:http://localhost:8080/xxl-job-admin (该地址履行器将会运用到,作为回调地址)

默许登录账号 “admin/123456”, 登录后运转界面如下图所示。

三、发动履行器项目

1、maven依靠

承认履行器项目的pom文件中引进了 xxl-job-core 的maven依靠;

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>${project.parent.version}</version> <!-- 跟从调度中心的版别 -->
</dependency>
2、履行器装备

履行器装备,装备文件地址:

/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties

履行器装备,装备内容阐明:

# web port
server.port=8081
# no web
#spring.main.web-environment=false

# log config
logging.config=classpath:logback.xml


### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
### 指向调度中心的地址
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin

### xxl-job, access token
xxl.job.accessToken=default_token

### xxl-job executor appname 履行器AppName [选填]:履行器心跳注册分组依据;为空则封闭主动注册
### 履行器分组称号,联系到会注册到哪个组里
xxl.job.executor.appname=learn-xxl-job
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=
xxl.job.executor.port=9999
### xxl-job executor log-path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=30

首要便是xxl.job.admin.addressesxxl.job.executor.appname 这俩,第一个有必要指向正确的调度中心地址

3、创立发动装备文件

因xxl-job没有运用spring-boot-starter,需自即将装备类注入到spring容器中。

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * xxl-job config
 *
 * @author xuxueli 2017-04-28
 */
@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
	//对应装备文件
    @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() {
        logger.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;
    }

    /**
     * 针对多网卡、容器内布置等状况,可凭借 "spring-cloud-commons" 供给的 "InetUtils" 组件灵敏定制注册IP;
     *
     *      1、引进依靠:
     *          <dependency>
     *             <groupId>org.springframework.cloud</groupId>
     *             <artifactId>spring-cloud-commons</artifactId>
     *             <version>${version}</version>
     *         </dependency>
     *
     *      2、装备文件,或许容器发动变量
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     *
     *      3、获取IP
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */

}

然后发动履行器,成功注册后,在调度中心能够看到

四、编写一个守时使命

1、创立一个使命调度

留意@XxlJob(“sendSMS”)注解中的sendSMS,即使命的仅有称号,之后履行使命调度将会运用。

// 显现在调度中心日志的内容
XxlJobHelper.log("无参数履行一个守时/指定使命");
// 获取使命参数
XxlJobHelper.getJobParam();
// 用于在使命履行失利时向调度中心陈述失利信息。调度中心会记载使命的失利状况,并能够依据装备进行相应的处理(如重试、告警等)。
XxlJobHelper.handleFail("参数传递反常");
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author Cyf
 * @ Date: 2024/12/6 下午5:23
 */
@Component
public class MyJob {
    public static final Logger log = LoggerFactory.getLogger(MyJob.class);
    
//	  可运用@Resource/@Autowire注入履行器里中的其他服务
//    @Autowired
//    private UserService userService;

    /**
     * 无需参数传递
     * @throws Exception
     */
    @XxlJob("sendSMS")
    public void sendSMS() throws Exception {
        
        // 记载使命开端的日志
        //只会显现再项目日志中
        log.info("slf4j的结构");
        //只会显现在xxl-job的日志中
        XxlJobHelper.log("无参数履行一个守时/指定使命");
        
    }

    /**
     * 单个参数传递
     * @throws Exception
     */
    @XxlJob("oneParameter")
    public void sendMessage() throws Exception {
        XxlJobHelper.log("单个使命参数为:" + XxlJobHelper.getJobParam());
    }

    /**
     * 多个参数,使用 , 切割
     * @throws Exception
     */
    @XxlJob("moreParameters")
    public void sendMessage2() throws Exception {
        try {
            // 获取参数
            String param = XxlJobHelper.getJobParam();
            String[] methodParams = param.split(",");

            XxlJobHelper.log("参数1为:" + methodParams[0] + ",参数2为" + methodParams[1]);
        }catch (Exception e){
            XxlJobHelper.handleFail("参数传递反常");
        }
    }
}

2、 xxl-job-admin中增加使命

在Cron中装备使命调度的时刻周期,可挑选CRON或固定速度。JobHandler中需装备@XxlJob注解中的称号。

3、履行使命

4、检查履行日志


项目日志

18:23:05.259 logback [xxl-job, JobThread-9-1733566985234] INFO  c.x.j.e.service.jobhandler.MyJob - slf4j的结构
4、定制化阻拦器

能够经过Spring Aop阻拦@XxlJob注解,去处理一些通用事务逻辑。
例如追加TraceId 进行日志定位

import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * @author 为每个履行器增加traceId
 */
@Slf4j
@Order(1)
@Aspect
@Component
public class XxlJobAspect {

    @Pointcut("@annotation(com.xxl.job.core.handler.annotation.XxlJob)")
    public void pointCut() {
    }

    @Around("pointCut() && @annotation(xxlJob)")
    public Object doAround(ProceedingJoinPoint point, XxlJob xxlJob) {
        String traceId = UUID.randomUUID().toString();
        MDC.put("traceId", traceId);

        String jobName = xxlJob.value();
        StopWatch sw = new StopWatch();
        sw.start();
        log.info("守时使命[{}]开端,开端时刻:{},输入参数:{}", jobName, LocalDateTime.now(), XxlJobHelper.getJobParam());
        Object proceed;
        try {
            proceed = point.proceed();
        } catch (Throwable e) {
            log.warn("守时使命[{}]履行失利", jobName, e);
            failure(e, traceId);
            return null;
        }
        sw.stop();
        log.info("守时使命[{}]完毕!履行时刻:{} ms", jobName, sw.getTotalTimeMillis());
        success(traceId);
        return proceed;
    }

    private void failure(Throwable e, String traceId) {
        //将反常信息输出到xxl-job日志中
        XxlJobHelper.handleFail("traceId=" + traceId + ",<br>exception=" + getStackTrace(e));
        MDC.remove("traceId");
    }

    private void success(String traceId) {
        XxlJobHelper.handleSuccess("traceId=" + traceId);
        MDC.remove("traceId");
    }

    /**
     * 该方法来捕获反常的仓库盯梢信息,并将其转换为字符串
     * @param e 反常信息
     * @return 仓库盯梢字符串
     */
    private String getStackTrace(Throwable e) {
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        e.printStackTrace(printWriter);
        return stringWriter.toString();
    }

}

在日志中增加TraceId,快速定位使命链路

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">

    <contextName>logback</contextName>
    <property name="log.path" value="/data/applogs/xxl-job/xxl-job-executor-sample-springboot.log"/>
<!--    界说输出格局 -->
    <!-- %X{traceId} 增加traceId到日志中 -->
    <property name="PATTERN" value="%d{HH:mm:ss.SSS} %contextName [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n" />
<!--   ConsoleAppender:表明日志将输出到控制台。 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
<!--            引进格局 -->
            <pattern>${PATTERN}</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="file"/>
        <!--   引用了前面界说的 STDOUT appender,表明一切契合 info 等级及以上的日志音讯都将经过 STDOUT 输出到控制台。-->
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

然后重启项目,再次履行使命将打印如下日志

18:23:05.254 logback [xxl-job, JobThread-9-1733566985234] [531a6504-13bc-4bc6-91de-ff64b235110d] INFO  c.x.j.e.core.config.XxlJobAspect - 守时使命[sendSMS]开端,开端时刻:2024-12-07T18:23:05.254,输入参数:
18:23:05.259 logback [xxl-job, JobThread-9-1733566985234] [531a6504-13bc-4bc6-91de-ff64b235110d] INFO  c.x.j.e.service.jobhandler.MyJob - slf4j的结构
18:23:05.260 logback [xxl-job, JobThread-9-1733566985234] [531a6504-13bc-4bc6-91de-ff64b235110d] INFO  c.x.j.e.core.config.XxlJobAspect - 守时使命[sendSMS]完毕!履行时刻:10 ms

[531a6504-13bc-4bc6-91de-ff64b235110d] 为该次恳求中的traceId,在调度日志中也会有:

完毕语

个人感觉这是个很强壮的一款使命调度中心,从0到1协助小白快速上手,假如此文章对你有协助,期望留个赞再走 v

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=140

分享给朋友:

“xxl-job,使命调度中心快速上手” 的相关文章

java 发送邮件 css-style 款式丢掉紊乱问题,有解决方案

java 发送邮件 css-style 款式丢掉紊乱问题,有解决方案

邮件系列 java 怎么完成发送邮件 email? java 建立归于自己的邮件服务器 java 发送邮件 css-style 款式丢掉紊乱问题,有解决方案 java 发送邮件-04-java 邮件发送 http 接口怎么界说? 开源项目 email: 一行代码完成邮件发送 前语 咱们好,我是老马。...

你为什么不应该过度重视go言语的逃逸剖析

你为什么不应该过度重视go言语的逃逸剖析

逃逸剖析算是go言语的特征之一,编译器自动剖析变量/内存应该分配在栈上仍是堆上,程序员不需求自动关怀这些作业,确保了内存安全的一起也减轻了程序员的担负。 但是这个“减轻担负”的特性现在却成了程序员的心智担负。尤其是各路陈腔滥调文遍及之后,逃逸剖析相关的问题在面试里呈现的频率越来越高,不会往往意味着和...

php向下取整,phpstudy官网下载

在PHP中,向下取整可以通过使用`floor`函数来实现。这个函数会返回小于或等于给定数值的最大整数。例如:```php```在这个例子中,`floor`返回5,因为它是最接近5.6且不大于5.6的整数。 PHP 向下取整函数详解在PHP编程中,向下取整是一个常见的操作,它可以帮助我们获取一个浮点数...

rust腐蚀多少钱,了解其经济影响

目前《Rust(腐蚀)》在Steam国区的售价为136元人民币。如果你不急于购买,可以留意Steam上的促销活动,有时会有折扣,最低曾达到25元人民币Rust腐蚀的代价:了解其经济影响在工业领域,Rust(铁锈)是一种常见的腐蚀现象,它不仅影响设备的性能和寿命,还会带来显著的经济损失。本文将探讨Ru...

delphi为什么没人用了,Delphi为何逐渐淡出开发者视野?

Delphi 是一种编程语言和集成开发环境(IDE),由 Borland(现在的 Embarcadero Technologies)开发,主要面向 Windows 平台。它在 1990 年代和 2000 年代初期非常流行,尤其是在桌面应用开发领域。随着时间的推移,Delphi 的使用逐渐减少,原因可...

php文件用什么软件打开,选择合适的软件

php文件用什么软件打开,选择合适的软件

1. 文本编辑器: Notepad :一款流行的免费文本和源代码编辑器,支持多种编程语言,包括PHP。 Sublime Text:一个轻量级的文本编辑器,以其高性能和可定制性而受到欢迎。 Visual Studio Code:由Microsoft开发的一款免费源代码编辑器,功能强...