xxl-job分布式任務調度


git地址: https://github.com/xuxueli/xxl-job

一個分布式的任務調度框架,官網文檔寫的非常詳細,只是簡單的記錄下。

1. 部署admin項目

  admin項目是一個可視化管理控制的項目。

 1.下載

到碼雲克隆項目:http://gitee.com/xuxueli0323/xxl-job

 2.到數據庫執行腳本

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

3.編譯源碼

xxl-job-admin:調度中心
xxl-job-core:公共依賴
xxl-job-executor-samples:執行器Sample示例(選擇合適的版本執行器,可直接使用,也可以參考其並將現有項目改造成執行器)
    :xxl-job-executor-sample-springboot:Springboot版本,通過Springboot管理執行器,推薦這種方式;
    :xxl-job-executor-sample-spring:Spring版本,通過Spring容器管理執行器,比較通用;
    :xxl-job-executor-sample-frameless:無框架版本;
    :xxl-job-executor-sample-jfinal:JFinal版本,通過JFinal管理執行器;
    :xxl-job-executor-sample-nutz:Nutz版本,通過Nutz管理執行器;
    :xxl-job-executor-sample-jboot:jboot版本,通過jboot管理執行器;

4.配置調度中心

xxl-job-admin 是項目的配置中心。導入IDEA,maven環境配置好之后啟動是非常方便的。

1. 需要改一下數據庫的連接信息

2.啟動主類

3.啟動后訪問8080端口就可以

4.登錄  賬號密碼是  admin/123456

5.界面如下:

 2. 配置項目執行器項目

   這個就是實際工作的項目。這個是xxl-job自帶的項目。

1.啟動xxl-job-executor-sample-springboot 項目

2. 控制台執行

3. 啟動后從admin管理項目運行一次

到任務管理執行一次即可。

4.查看啟動日志

2020-11-15 14:09:00 [com.xxl.job.core.thread.JobThread#run]-[130]-[Thread-39] 
----------- xxl-job job execute start -----------
----------- Param:
2020-11-15 14:09:00 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[39]-[Thread-39] XXL-JOB, Hello World.
2020-11-15 14:09:00 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:0
2020-11-15 14:09:02 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:1
2020-11-15 14:09:04 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:2
2020-11-15 14:09:06 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:3
2020-11-15 14:09:08 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:4
2020-11-15 14:09:10 [com.xxl.job.core.thread.JobThread#run]-[176]-[Thread-39] 
----------- xxl-job job execute end(finish) -----------
----------- Result: handleCode=200, handleMsg = null
2020-11-15 14:09:10 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[197]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

 

3 .模仿上面項目自建任務在Springboot中運行

 1.新建項目cloud-xxl-job-8081

 2.修改pom

<?xml version="1.0" encoding="UTF-8"?>
<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>cloud</artifactId>
        <groupId>cn.qz.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-xxl-job-8081</artifactId>

    <dependencies>
        <!-- xxl-job-core -->
        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!--引入自己抽取的工具包-->
        <dependency>
            <groupId>cn.qz.cloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3. 新增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=
### xxl-job executor appname
xxl.job.executor.appname=xxl-job-executor-test
### 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.addresses=http://127.0.0.1:8080/xxl-job-admin
### 執行器通訊TOKEN [選填]:非空時啟用;
xxl.job.accessToken=
### 執行器AppName [選填]:執行器心跳注冊分組依據;為空則關閉自動注冊
xxl.job.executor.appname=xxl-job-executor-sample
### 執行器注冊 [選填]:優先使用該配置作為注冊地址,為空時使用內嵌服務 ”IP:PORT“ 作為注冊地址。從而更靈活的支持容器類型執行器動態IP和動態映射端口問題。
xxl.job.executor.address=
### 執行器IP [選填]:默認為空表示自動獲取IP,多網卡時可手動設置指定IP,該IP不會綁定Host僅作為通訊實用;地址信息用於 "執行器注冊" 和 "調度中心請求並觸發任務";
xxl.job.executor.ip=
### 執行器端口號 [選填]:小於等於0則自動獲取;默認端口為9999,單機部署多個執行器時,注意要配置不同執行器端口;
xxl.job.executor.port=9999
### 執行器運行日志文件存儲磁盤路徑 [選填] :需要對該路徑擁有讀寫權限;為空則使用默認路徑;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 執行器日志文件保存天數 [選填] : 過期日志自動清理, 限制值大於等於3時生效; 否則, 如-1, 關閉自動清理功能;
xxl.job.executor.logretentiondays=30

4. 主啟動類

package cn.qz.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @Author: qlq
 * @Description
 * @Date: 14:44 2020/11/15
 */
@SpringBootApplication
public class XXLJobMain8081 {

    public static void main(String[] args) {
        SpringApplication.run(XXLJobMain8081.class, args);
    }

}

5.業務類

  有兩種方式。第一種是基於方法上面增加注解@XxlJob;第二種是類繼承IJobHandler,然后通過手動注入到執行器容器。

(1)  方法加注解 @XxlJob  實現

package cn.qz.cloud.job;

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @Author: qlq
 * @Description
 * @Date: 15:22 2020/11/15
 */
@Slf4j
@Component
public class FirstJob {

    @XxlJob(value = "firstJob", init = "init", destroy = "destroy")
    public ReturnT<String> execute(String param) {
        XxlJobLogger.log("XXL-JOB, firstJob. param: {}", param);
        log.info("XXL-JOB, firstJob. param: {}", param);
        return ReturnT.SUCCESS;
    }

    public void init() {
        log.info("init");
    }

    public void destroy() {
        log.info("destory");
    }
}

  XxlJobLogger.log是記錄到xxl-job-admin 的日志收集器里面,可以從admin管理台查看;普通的log記錄是記錄到我們系統的日志搜集器里面。

(2) 繼承IJobHandler的方式

package cn.qz.cloud.job;

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @Author: qlq
 * @Description
 * @Date: 15:22 2020/11/15
 */
@Slf4j
public class XXLClassJob extends IJobHandler {

    @Override
    public ReturnT<String> execute(String param) throws Exception {
        log.info("XXLClassJob execute, param: {}", param);
        XxlJobLogger.log("XXLClassJob execute, param: {}", param);

        for (int i = 0; i < 5; i++) {
            log.info("XXLClassJob start, i: {} ", i);
            XxlJobLogger.log("XXLClassJob start, i: {} ", i);
            TimeUnit.SECONDS.sleep(2);
        }
        return ReturnT.SUCCESS;
    }
}

(3) 配置類: 注意需要手動將job注入到執行器容器

package cn.qz.cloud.config;

import cn.qz.cloud.job.XXLClassJob;
import com.xxl.job.core.executor.XxlJobExecutor;
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;

/**
 * @Author: qlq
 * @Description
 * @Date: 17:02 2020/11/15
 */
@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    static {
        // 手動通過如下方式注入到執行器容器。
        XxlJobExecutor.registJobHandler("XXLClassJob", new XXLClassJob());
    }

    @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;
    }
}

6. 啟動主類

20:46:27.096 logback [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8081"]
20:46:27.238 logback [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8081 (http) with context path ''
20:46:27.252 logback [main] INFO  cn.qz.cloud.XXLJobMain8081 - Started XXLJobMain8081 in 20.195 seconds (JVM running for 23.668)
20:46:37.301 logback [Thread-5] INFO  com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999
20:47:00.694 logback [xxl-rpc, EmbedServer bizThreadPool-1961798941] INFO  c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:4, handler:com.xxl.job.core.handler.impl.MethodJobHandler@42ea7565[class cn.qz.cloud.job.FirstJob#execute]
20:47:00.695 logback [Thread-8] INFO  cn.qz.cloud.job.FirstJob - init
20:47:00.715 logback [xxl-rpc, EmbedServer bizThreadPool-1961798941] INFO  c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:5, handler:cn.qz.cloud.job.XXLClassJob@23706db8

可以看到啟動了一個內嵌的服務9999端口。通過netstat -ano 也可以查看9999端口,如果之后測試報錯可以查看是否沒有監聽到某個端口。

7.在xxl-job-admin 界面進行設置

(1) 新建一個 執行器

 

 (2) 新建一個任務管理執行XXLClassJob 任務

(3)新建一個任務執行firstJob

 (4) 任務管理 -》 選擇一條任務之后執行一次  firstJob

到IDEA查看日志如下:

21:06:27.977 logback [xxl-rpc, EmbedServer bizThreadPool-1916408283] INFO  c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:4, handler:com.xxl.job.core.handler.impl.MethodJobHandler@523a7801[class cn.qz.cloud.job.FirstJob#execute]
21:06:27.983 logback [Thread-8] INFO  cn.qz.cloud.job.FirstJob - init
21:06:28.007 logback [Thread-8] INFO  cn.qz.cloud.job.FirstJob - XXL-JOB, firstJob. param: XXX

 然后可以到XxlJob-admin查看日志:

2020-11-15 21:06:27 [com.xxl.job.core.thread.JobThread#run]-[124]-[Thread-8] 
----------- xxl-job job execute start -----------
----------- Param:XXX
2020-11-15 21:06:28 [cn.qz.cloud.job.FirstJob#execute]-[20]-[Thread-8] XXL-JOB, firstJob. param: XXX
2020-11-15 21:06:28 [com.xxl.job.core.thread.JobThread#run]-[164]-[Thread-8] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-11-15 21:06:28 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

 8. 簡單的測下分布式環境控制哪個機器執行任務

1. 再啟動一個執行項目,項目端口8082;xxl.job.executor.port 改為9998

2. 從admin查看機器地址有兩個,如下:

 3. 編輯任務可以看到有好幾種策略。這些策略是說從哪個機器執行上面的任務,類似於一個應該多實例部署,我們可以手動設置哪個實例執行任務。有點類似於負載均衡。

 4.我們改為輪詢即可,可以通過執行日志查看到是兩個機器替換着執行

9. GLUE模式(Java)  簡單使用

 上面的模式可以稱為Bean模式,符合常見的開發思想。

 “GLUE模式(Java)”的執行代碼托管到調度中心在線維護,相比“Bean模式任務”需要在執行器項目開發部署上線,更加簡便輕量),可使用@Resource/@Autowire注入執行器里中的其他服務。前提是“調度中心”和“執行器”項目已經成功部署並啟動。這種模式實現是利用groovy將類信息加載到JVM中。

1.新建一個任務管理,模式選擇GLUE

 2. 任務管理選擇一條任務 操作-》 GLUE IDE,代碼如下:

package cn.qz.cloud.job;

import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @Author: qlq
 * @Description
 * @Date: 15:22 2020/11/15
 */
public class XXLClassJob2 extends IJobHandler {

    @Override
    public ReturnT<String> execute(String param) throws Exception {
          System.out.println("param : " + param);
        XxlJobLogger.log("XXLClassJob2 execute, param: {}", param);

        for (int i = 0; i < 5; i++) {
            XxlJobLogger.log("XXLClassJob2 Glue start, i: {} ", i);
            TimeUnit.SECONDS.sleep(2);
        }
        return ReturnT.SUCCESS;
    }
}

3.執行一次后可以到IDEA查看日志,同時查看執行日志如下:

2020-11-15 21:42:59 [com.xxl.job.core.thread.JobThread#run]-[124]-[Thread-15] 
----------- xxl-job job execute start -----------
----------- Param:這是Glue參數
2020-11-15 21:42:59 [com.xxl.job.core.handler.impl.GlueJobHandler#execute]-[26]-[Thread-15] ----------- glue.version:1605447731000 -----------
2020-11-15 21:42:59 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 execute, param: 這是Glue參數
2020-11-15 21:42:59 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 0 
2020-11-15 21:43:01 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 1 
2020-11-15 21:43:03 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 2 
2020-11-15 21:43:05 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 3 
2020-11-15 21:43:07 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 4 
2020-11-15 21:43:09 [com.xxl.job.core.thread.JobThread#run]-[164]-[Thread-15] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-11-15 21:43:09 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

 

  至此簡單的實現了分布式環境下的任務調度。當任務在多個實例部署的時候,可以在xxl-job的管理界面選擇執行任務的機器。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM