Java 定時任務調度(7)--XXL-JOB 入門實戰


在系統開發不可以避免的要使用到定時任務,簡單的任務可以使用spring的@Scheduled注解或者quartz來實現,但對於復雜的任務最好使用分布式的調度框架來處理,這樣可以部署集群,保證系統的擴展性及高可用性。本文主要介紹XXL-JOB的基本使用,詳細說明請參考官方文檔:https://www.xuxueli.com/xxl-job;文中使用到的軟件及版本:XXL-JOB 2.2.0、SpringBoot 2.2.5.RELEASE、Java 1.8.0_191、MySQL 5.7。

1、@Scheduled及Quartz的不足

1.1、@Scheduled的不足

Spring的@Scheduled對於單機的簡單任務使用起來很方便,但只能單節點運行,不利於橫向擴展。

1.2、Quartz的不足

Quartz作為開源作業調度中的佼佼者,是作業調度的首選。但是集群環境中Quartz存在以下問題:
問題一:調用API的的方式操作任務,不人性化;
問題二:需要持久化業務QuartzJobBean到底層數據表中,系統侵入性相當嚴重;
問題三:調度邏輯和QuartzJobBean耦合在同一個項目中,這將導致一個問題,在調度任務數量逐漸增多,同時調度任務邏輯逐漸加重的情況下,此時調度系統的性能將大大受限於業務;
問題四:quartz底層以“搶占式”獲取DB鎖並由搶占成功節點負責運行任務,會導致節點負載懸殊非常大;


XXL-JOB彌補了quartz的上述不足之處。

2、XXL-JOB使用

2.1、下載源碼

下載地址:https://github.com/xuxueli/xxl-job,下載后用idea打開:

2.2、初始化調度數據庫

SQL腳本位置為:

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

2.3、配置部署調度中心(xxl-job-admin)

2.3.1、配置修改

配置文件路徑為:

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

修改配置文件中的數據庫的相關信息,其他參數根據需要修改:

spring.datasource.url=jdbc:mysql://10.49.196.10:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=admin
spring.datasource.password=Root_123!
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

2.3.2、部署調度中心

調度中心是一個SpringBoot的工程,在本地可以直接運行,或打成jar包到服務器上運行。

調度中心訪問地址:http://localhost:8080/xxl-job-admin (該地址執行器將會使用到,作為回調地址)
默認登錄賬號:admin/123456

2.3.3、調度中心集群部署

調度中心支持集群部署,提升調度系統容災和可用性。
調度中心集群部署時,幾點要求和建議:
  DB配置保持一致;
  集群機器時鍾保持一致(單機集群忽視);
  建議:推薦通過nginx為調度中心集群做負載均衡,分配域名。調度中心訪問、執行器回調配置、調用API服務等操作均通過該域名進行。

2.4、配置部署執行器項目

可以直接在運行XXL-JOB自帶的樣例執行器項目xxl-job-executor-sample-springboot(需要修改數據庫等配置參數再運行),這里自己使用SpringBoot來開發執行器。

2.4.1、引入依賴

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.2.0</version>
</dependency>

2.4.2、執行器配置文件修改

拷貝/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties中的配置信息到自己SpringBoot工程中的配置文件中,並根據需要修改對應的配置信息。

# 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-sample
### 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=10.39.196.58
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

2.4.3、執行器配置

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

可以直接拷貝/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java到自己的工程中。

2.4.4、部署執行器

執行器是一個SpringBoot的工程,在本地可以直接運行,或打成jar包到服務器上運行。

2.4.5、執行器集群部署(可選)

執行器支持集群部署,提升調度系統可用性,同時提升任務處理能力。
執行器集群部署時,幾點要求和建議:
  執行器回調地址(xxl.job.admin.addresses)需要保持一致;執行器根據該配置進行執行器自動注冊等操作。
  同一個執行器集群內AppName(xxl.job.executor.appname)需要保持一致;調度中心根據該配置動態發現不同集群的在線執行器列表。

2.5、任務創建

2.5.1、BEAN模式任務

任務以JobHandler方式維護在執行器端;前台結合 "JobHandler" 屬性匹配執行器中任務。

2.5.1.1、開發JobHandler

在執行器的項目中新建類,方法上增加@XxlJob注解即表示一個JobHandler。

@Component
public class TestJob {
    protected static Logger logger = LoggerFactory.getLogger(TestJob.class);

    @XxlJob("testJobHandler")
    public ReturnT<String> testJobHandler(String param) throws Exception {
        XxlJobLogger.log("test-JOB, Hello World.");

        for (int i = 0; i < 5; i++) {
            //XxlJobLogger打印的日志可以在控制台查看
            XxlJobLogger.log("beat at:" + i);
            logger.info("beat at:" + i);
            TimeUnit.SECONDS.sleep(2);
        }
        return ReturnT.SUCCESS;
    }
}
2.5.1.2、前台配置任務

JobHandler填的值對應上一步@XxlJob中的值。

2.5.2、GLUE模式(Java)任務

任務以源碼方式維護在調度中心;該模式的任務實際上是一段繼承自IJobHandlerJava類代碼,它在執行器項目中運行,可使用@Resource/@Autowire注入執行器里中的其他服務.

 保存后在“操作”中點擊GLUE IDE:

 


免責聲明!

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



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