xxl-job的部署及springboot集成使用

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: XXL-Job是一个分布式任务调度平台,可进行任务调度、管理和监控,并提供任务分片、失败重试、动态分配等功能。它是一个开源项目,基于Spring Boot和Quartz开发,支持常见的任务调度场景。XXL-Job的使用相对简单,只需要简单配置即可实现任务调度。同时,它提供了丰富的管理和监控功能,可以方便地查看任务执行状态、日志等。在企业中,XXL-Job广泛应用于一些大型、分布式的系统中,如电商系统、金融系统等。它的高性能、高可靠性、易使用性等特点深受用户的喜爱。

# 介绍

XXL-Job是一个分布式任务调度平台,可进行任务调度、管理和监控,并提供任务分片、失败重试、动态分配等功能。它是一个开源项目,基于Spring Boot和Quartz开发,支持常见的任务调度场景。


XXL-Job的使用相对简单,只需要简单配置即可实现任务调度。同时,它提供了丰富的管理和监控功能,可以方便地查看任务执行状态、日志等。


在企业中,XXL-Job广泛应用于一些大型、分布式的系统中,如电商系统、金融系统等。它的高性能、高可靠性、易使用性等特点深受用户的喜爱。


# 1.安装mysql

```

docker run -d \

--name mysql \

-p 3306:3306 \

-e MYSQL_ROOT_PASSWORD=root1234567 \

mysql:8.0

```

# 2.初始化下载的数据

https://github.com/xuxueli/xxl-job/releases

https://github.com/xuxueli/xxl-job/archive/refs/tags/2.4.0.tar.gz

解压后执行xxl-job-2.4.0.tar\xxl-job-2.4.0\doc\db\tables_xxl_job.sql


# 3.启动xxl-job-admin

默认登录 admin/123456

```

docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://172.24.31.53:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai

--spring.datasource.username=root --spring.datasource.password=root1234567" -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin  -d  xuxueli/xxl-job-admin:2.4.0

```


http://172.24.31.53:8080/xxl-job-admin/


![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/a1584966b2bf42afb35f5ece6691604d.png)




# 3.springboot集成

## 3.1依赖

```

<dependency>

  <groupId>com.xuxueli</groupId>

  <artifactId>xxl-job-core</artifactId>

  <version>2.4.0</version>

 </dependency>

```

## 3.2配置

```

xxl:

 job:

   admin:

     addresses: http://101.200.153.111:8080/xxl-job-admin

   accessToken: default_token

   executor:

     appname: xxl-job-executor-sample

     address:

     ip: 101.200.153.111

     port: 4567

     logpath: /data/applogs/xxl-job/jobhandler

     logretentiondays: 30

```



## 3.3代码

```

package com.lys.lys_admin_api.xxl;


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 https://liuyunshengsir.blog.csdn.net/

*/

@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();

    */



}

```

jobhandler 样例

```

package com.lys.lys_admin_api.xxl.jobhandler;


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;


import java.io.BufferedInputStream;

import java.io.BufferedReader;

import java.io.DataOutputStream;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.Arrays;

import java.util.concurrent.TimeUnit;


/**

* XxlJob开发示例(Bean模式)

*

* 开发步骤:

*      1、任务开发:在Spring Bean实例中,开发Job方法;

*      2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。

*      3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志;

*      4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果;

*

* @author https://liuyunshengsir.blog.csdn.net/

*/

@Component

public class SampleXxlJob {

   private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);



   /**

    * 1、简单任务示例(Bean模式)

    */

   @XxlJob("demoJobHandlerLYS")

   public void demoJobHandler() throws Exception {

       XxlJobHelper.log("XXL-JOB, Hello World.");


       for (int i = 0; i < 5; i++) {

           XxlJobHelper.log("beat at:" + i);

           TimeUnit.SECONDS.sleep(2);

       }

       // default success

   }



   /**

    * 2、分片广播任务

    */

   @XxlJob("shardingJobHandler")

   public void shardingJobHandler() throws Exception {


       // 分片参数

       int shardIndex = XxlJobHelper.getShardIndex();

       int shardTotal = XxlJobHelper.getShardTotal();


       XxlJobHelper.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);


       // 业务逻辑

       for (int i = 0; i < shardTotal; i++) {

           if (i == shardIndex) {

               XxlJobHelper.log("第 {} 片, 命中分片开始处理", i);

           } else {

               XxlJobHelper.log("第 {} 片, 忽略", i);

           }

       }


   }



   /**

    * 3、命令行任务

    */

   @XxlJob("commandJobHandler")

   public void commandJobHandler() throws Exception {

       String command = XxlJobHelper.getJobParam();

       int exitValue = -1;


       BufferedReader bufferedReader = null;

       try {

           // command process

           ProcessBuilder processBuilder = new ProcessBuilder();

           processBuilder.command(command);

           processBuilder.redirectErrorStream(true);


           Process process = processBuilder.start();

           //Process process = Runtime.getRuntime().exec(command);


           BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());

           bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));


           // command log

           String line;

           while ((line = bufferedReader.readLine()) != null) {

               XxlJobHelper.log(line);

           }


           // command exit

           process.waitFor();

           exitValue = process.exitValue();

       } catch (Exception e) {

           XxlJobHelper.log(e);

       } finally {

           if (bufferedReader != null) {

               bufferedReader.close();

           }

       }


       if (exitValue == 0) {

           // default success

       } else {

           XxlJobHelper.handleFail("command exit value("+exitValue+") is failed");

       }


   }



   /**

    * 4、跨平台Http任务

    *  参数示例:

    *      "url: http://www.baidu.com\n" +

    *      "method: get\n" +

    *      "data: content\n";

    */

   @XxlJob("httpJobHandler")

   public void httpJobHandler() throws Exception {


       // param parse

       String param = XxlJobHelper.getJobParam();

       if (param==null || param.trim().length()==0) {

           XxlJobHelper.log("param["+ param +"] invalid.");


           XxlJobHelper.handleFail();

           return;

       }


       String[] httpParams = param.split("\n");

       String url = null;

       String method = null;

       String data = null;

       for (String httpParam: httpParams) {

           if (httpParam.startsWith("url:")) {

               url = httpParam.substring(httpParam.indexOf("url:") + 4).trim();

           }

           if (httpParam.startsWith("method:")) {

               method = httpParam.substring(httpParam.indexOf("method:") + 7).trim().toUpperCase();

           }

           if (httpParam.startsWith("data:")) {

               data = httpParam.substring(httpParam.indexOf("data:") + 5).trim();

           }

       }


       // param valid

       if (url==null || url.trim().length()==0) {

           XxlJobHelper.log("url["+ url +"] invalid.");


           XxlJobHelper.handleFail();

           return;

       }

       if (method==null || !Arrays.asList("GET", "POST").contains(method)) {

           XxlJobHelper.log("method["+ method +"] invalid.");


           XxlJobHelper.handleFail();

           return;

       }

       boolean isPostMethod = method.equals("POST");


       // request

       HttpURLConnection connection = null;

       BufferedReader bufferedReader = null;

       try {

           // connection

           URL realUrl = new URL(url);

           connection = (HttpURLConnection) realUrl.openConnection();


           // connection setting

           connection.setRequestMethod(method);

           connection.setDoOutput(isPostMethod);

           connection.setDoInput(true);

           connection.setUseCaches(false);

           connection.setReadTimeout(5 * 1000);

           connection.setConnectTimeout(3 * 1000);

           connection.setRequestProperty("connection", "Keep-Alive");

           connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");

           connection.setRequestProperty("Accept-Charset", "application/json;charset=UTF-8");


           // do connection

           connection.connect();


           // data

           if (isPostMethod && data!=null && data.trim().length()>0) {

               DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());

               dataOutputStream.write(data.getBytes("UTF-8"));

               dataOutputStream.flush();

               dataOutputStream.close();

           }


           // valid StatusCode

           int statusCode = connection.getResponseCode();

           if (statusCode != 200) {

               throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid.");

           }


           // result

           bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));

           StringBuilder result = new StringBuilder();

           String line;

           while ((line = bufferedReader.readLine()) != null) {

               result.append(line);

           }

           String responseMsg = result.toString();


           XxlJobHelper.log(responseMsg);


           return;

       } catch (Exception e) {

           XxlJobHelper.log(e);


           XxlJobHelper.handleFail();

           return;

       } finally {

           try {

               if (bufferedReader != null) {

                   bufferedReader.close();

               }

               if (connection != null) {

                   connection.disconnect();

               }

           } catch (Exception e2) {

               XxlJobHelper.log(e2);

           }

       }


   }


   /**

    * 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑;

    */

   @XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")

   public void demoJobHandler2() throws Exception {

       XxlJobHelper.log("XXL-JOB, Hello World.");

   }

   public void init(){

       logger.info("init");

   }

   public void destroy(){

       logger.info("destroy");

   }



}


```

## 3.4 页面查看

![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/f3c93ab10d774e3cb0ef71555decf4df.png)







相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
16天前
|
前端开发 Java 应用服务中间件
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
该文是一系列关于从零开始手写实现 Apache Tomcat 的教程概述。作者希望通过亲自动手实践理解 Tomcat 的核心机制。文章讨论了 Spring Boot 如何实现直接通过 `main` 方法启动,Spring 与 Tomcat 容器的集成方式,以及两者生命周期的同步原理。文中还提出了实现 Tomcat 的启发,强调在设计启动流程时确保资源的正确加载和初始化。最后提到了一个名为 mini-cat(嗅虎)的简易 Tomcat 实现项目,开源于 [GitHub](https://github.com/houbb/minicat)。
|
1月前
|
消息中间件 Java Kafka
Springboot集成高低版本kafka
Springboot集成高低版本kafka
|
1月前
|
NoSQL Java Redis
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
376 0
|
1月前
|
存储 JSON Java
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
45 2
|
16天前
|
前端开发 Java 应用服务中间件
从零手写实现 tomcat-08-tomcat 如何与 springboot 集成?
本文探讨了Spring Boot如何实现像普通Java程序一样通过main方法启动,关键在于Spring Boot的自动配置、内嵌Servlet容器(如Tomcat)以及`SpringApplication`类。Spring与Tomcat集成有两种方式:独立模式和嵌入式模式,两者通过Servlet规范、Spring MVC协同工作。Spring和Tomcat的生命周期同步涉及启动、运行和关闭阶段,通过事件和监听器实现。文章鼓励读者从实现Tomcat中学习资源管理和生命周期管理。此外,推荐了Netty权威指南系列文章,并提到了一个名为mini-cat的简易Tomcat实现项目。
|
3天前
|
消息中间件 JSON Java
RabbitMQ的springboot项目集成使用-01
RabbitMQ的springboot项目集成使用-01
|
3天前
|
搜索推荐 Java 数据库
springboot集成ElasticSearch的具体操作(系统全文检索)
springboot集成ElasticSearch的具体操作(系统全文检索)
|
3天前
|
消息中间件 Java Spring
Springboot 集成Rabbitmq之延时队列
Springboot 集成Rabbitmq之延时队列
4 0
|
3天前
|
网络协议 Java Spring
Springboot 集成websocket
Springboot 集成websocket
7 0
|
3天前
|
XML Java 数据库
springboot集成flowable
springboot集成flowable