分布式任务调度平台 XXL-JOB 快速入门使用

一、分布式任务调度概述

1、什么是任务调度平台

任务调度是指基于给定的时间点,给定的时间间隔又或者给定执行次数自动的执行任务。我们可以思考一下在以下场景中,我们应该怎么实现:

  • 支付系统每天凌晨 1 点,进行一天清算,每月 1 号进行上个月清算;

  • 电商整点抢购,商品价格8点整开始优惠

  • 12306 购票系统,超过 30 分钟没有成功支付订单的,进行回收处理

2、为什么需要任务调度平台

定时任务是程序员不可避免的话题,很多业务场景需要我们某一特定的时刻去做某件任务。一般来说,系统可以使用消息传递代替部分定时任务(比如商品成功发货后,需要向客户发送短信提醒),两者有很多相似之处,一些场景下也可以相互替换,但是有一些不能:

  • 时间驱动 / 事件驱动:内部系统一般可以通过事件来驱动,但如果涉及到外部系统,则只能使用时间驱动。如爬取外部网站价格,每小时爬一次。

  • 批量处理 / 逐条处理:批量处理堆积的数据更加高效,在不需要实时性的情况下比消息中间件更有优势。而且有的业务逻辑只能批量处理,如移动每个月结算我们的花费。

  • 实时性 / 非实时性:消息中间件能够做到实时处理数据,但是有些情况下并不需要实时,比如:vip 升级。

  • 系统内部 / 系统解耦:定时任务调度一般是在系统内部,而消息中间件可用于两个系统间

并且对于分布式系统来说,如果处理不当,会存在同一系统不同节点之间定时任务相互影响的问题,再考虑上监控、日志、信息面板,加上不同系统之间管理维护的问题,自己实现一套的成本又上来了..所以我们可以考虑一些比较成熟的任务调度平台来使用

3、任务调度框架选型

Java 领域主要分布式调度系统如下:

  • xxl-job:是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展 。

  • Elastic-Job:当当开源的分布式调度解决方案,由两个相互独立的子项目Elastic-Job-LiteElastic-Job-Cloud组成;

    • Elastic-Job-Lite:定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务;

    • Elastic-Job-Cloud 采用自研Mesos Framework的解决方案,额外提供资源治理、应用分发以及进程隔离等功能;

  • Saturn:是唯品会开源的一个分布式任务调度平台,在当当开源的Elastic Job基础上,取代传统的Linux Cron/Spring Batch Job的方式,做到全域统一配置,统一监控,任务高可用以及分片并发处理;

  • light-task-scheduler:阿里员工开源的个人项目,主要用于解决分布式任务调度问题,支持实时任务,定时任务和Cron任务。有较好的伸缩性,扩展性,健壮稳定性

  • Quartz: Java定时任务的标配。利用数据库的锁机制实现集群调度,业务代码需要考虑调度的逻辑,对业务代码有入侵。

二、XXL-JOB 分布式定时任务

XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

1、特性

1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;
2、动态:支持动态修改任务状态、启动/停止任务,以及终止运行中任务,即时生效;
3、调度中心HA(中心式):调度采用中心式设计,“调度中心”自研调度组件并支持集群部署,可保证调度中心HA;
4、执行器HA(分布式):任务分布式执行,任务”执行器”支持集群部署,可保证任务执行HA;
5、注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
6、弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
7、路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
8、故障转移:任务路由策略选择”故障转移”情况下,如果执行器集群中某一台机器故障,将会自动Failover切换到一台正常的执行器发送调度请求。
9、阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
10、任务超时控制:支持自定义任务超时时间,任务运行超时将会主动中断任务;
11、任务失败重试:支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;其中分片任务支持分片粒度的失败重试;
12、任务失败告警;默认提供邮件方式失败告警,同时预留扩展接口,可方便的扩展短信、钉钉等告警方式;
13、分片广播任务:执行器集群部署时,任务路由策略选择”分片广播”情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;
14、动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。
15、事件触发:除了”Cron方式”和”任务依赖方式”触发任务执行之外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
16、任务进度监控:支持实时监控任务进度;
17、Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
18、GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
19、脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS、PHP、PowerShell等类型脚本;
20、命令行任务:原生提供通用命令行任务Handler(Bean任务,”CommandJobHandler”);业务方只需要提供命令行即可;
21、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
22、一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
23、自定义任务参数:支持在线配置调度任务入参,即时生效;
24、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
25、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
26、邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
27、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
28、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
29、全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行;
30、跨语言:调度中心与执行器提供语言无关的 RESTful API 服务,第三方任意语言可据此对接调度中心或者实现执行器。除此之外,还提供了 “多任务模式”和“httpJobHandler”等其他跨语言方案;
31、国际化:调度中心支持国际化设置,提供中文、英文两种可选语言,默认为中文;
32、容器化:提供官方docker镜像,并实时更新推送dockerhub,进一步实现产品开箱即用;
33、线程池隔离:调度线程池进行隔离拆分,慢任务自动降级进入”Slow”线程池,避免耗尽调度线程,提高系统稳定性;
34、用户管理:支持在线管理系统用户,存在管理员、普通用户两种角色;
35、权限控制:执行器维度进行权限控制,管理员拥有全量权限,普通用户需要分配执行器权限后才允许相关操作;

三、快速入门 - 本地运行

先定个小目标,先把它在本地跑起来先。

1、源码下载地址

  • GitHub:https://github.com/xuxueli/xxl-job

  • 码云:https://gitee.com/xuxueli0323/xxl-job

2、文档地址

  • 中文文档:http://www.xuxueli.com/xxl-job/#/

  • 英文文档:http://www.xuxueli.com/xxl-job/en/#/

第一步:下载代码到本地

找一个合适的目录,然后执行下列语句把代码下载到本地:

$ git clone https://github.com/xuxueli/xxl-job.git

1594812590262.jpg

第二步:初始化数据库

找到 /xxl-job/doc/db/table_xxl_job.sql 初始化 SQL 脚本,将此脚本在MySQL数据库中执行一遍。

执行完毕,会在MySQL数据库中生成如下 8 张表:

图像2020-7-15 下午6.53 (1).jpeg

第三步:配置并启动 "调度中心"

调度中心配置文件地址:/xxl-job/xxl-job-admin/src/main/resources/xxl-job-admin.properties

调度中心配置内容说明:主要是 JDBC 链接、邮箱地址

### 调度中心JDBC链接:链接地址请保持和初始化时创建的数据库保持一致
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?Unicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root_pwd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

### 报警邮箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

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

该工程是一个springboot项目,我们只需要在IDEA中执行 XxlJobAdminApplication 类即可运行该工程:

在第一次启动的项目的时候可能会遇到找不到 log 文件的错误(Failed to create),我们只需要自己手动创建一下,或者修改一下 logback.xml 的日志路径

当一切配置好了之后,我们就可以启动项目了,调度中心访问地址:http://localhost:8080/xxl-job-admin(该地址执行期将会使用到,作为回调地址),默认登录账号 "admin/123456",登录后运行界面如下图所示:

1594812614530.jpg

至此,「调度中心」项目已经部署成功了,调度中心集群(可选)配置可参考官方文档。

第四步:配置启动"执行器"

执行器配置,配置文件地址:/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties

执行器配置,配置内容说明:

### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin

### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-sample

### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=

### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9999

### 执行器通讯TOKEN [选填]:非空时启用;(注意与调度中心保持一致)
xxl.job.accessToken=

### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler

### 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效;
xxl.job.executor.logretentiondays=-1

同样,也要注意一下"日志文件的创建和权限问题"。

当配置完成之后运行起来,我们就可以在刚才的任务调度中心的主页,在右上角的「执行器的数量」上 + 1 了。

第五步:执行一个任务

在“第二步:初始化数据库” 已经初始化了一个任务。

1594812630546.jpg

如上图,对应代码位置:/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java

@Component
public class SampleXxlJob {
    private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);


    /**
     * 1、简单任务示例(Bean模式)
     */
    @XxlJob("demoJobHandler")
    public ReturnT<String> demoJobHandler(String param) throws Exception {
        XxlJobLogger.log("XXL-JOB, Hello World.");

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

点击操作 中的 执行一次 按钮。输入一个 参数,单机保存

随后便有了执行日志,5.log 是递增执行。

1594812665740.jpg

单机操作中的 查看日志 观察执行结果。

1594812680995.jpg

第六步:开发第一个任务

经过测试的任务之后,开发一个自己的任务测试。

当「调度中心」和「执行器」都启动之后,我们可以直接在「调度中心」的任务管理界面新增一条配置如下图所示(参考)的任务:

1594812696099.jpg

任务详解

  • 执行器:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;

  • 任务描述:任务的描述信息,便于任务管理;

  • 路由策略:当执行器集群部署时,提供丰富的路由策略,包括;

    • FIRST(第一个):固定选择第一个机器;

    • LAST(最后一个):固定选择最后一个机器;

    • ROUND(轮询):;

    • RANDOM(随机):随机选择在线的机器;

    • CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。

    • LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举;

    • LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举;

    • FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;

    • BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;

    • SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;

  • Cron:触发任务执行的Cron表达式;

  • 运行模式

    • BEAN模式:任务以JobHandler方式维护在执行器端;需要结合 "JobHandler" 属性匹配执行器中任务;

    • GLUE模式(Java):任务以源码方式维护在调度中心;该模式的任务实际上是一段继承自IJobHandler的Java类代码并 "groovy" 源码方式维护,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务;

    • GLUE模式(Shell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "shell" 脚本;

    • GLUE模式(Python):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "python" 脚本;

    • GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "php" 脚本;

    • GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "nodejs" 脚本;

    • GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "PowerShell" 脚本;

  • JobHandler:运行模式为 "BEAN模式" 时生效,对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值;

  • 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略;

    • 单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;

    • 丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;

    • 覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;

  • 子任务:每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取),当本任务执行结束并且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。

  • 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;

  • 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;

  • 报警邮件:任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;

  • 负责人:任务的负责人;

  • 执行参数:任务执行所需的参数;

Bean模式又分为

  • Bean模式(类形式):基于类的开发方式,每个任务对应一个Java类。

  • Bean模式(方法形式):基于方法的开发方式,每个任务对应一个方法。

GLUE模式:

任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler

原生内置Bean模式任务

为方便用户参考与快速实用,执行器(SampleXxlJob 完整代码)内原生提供多个Bean模式任务Handler,可以直接配置实用,如下:

  • demoJobHandler:简单示例任务,任务内部模拟耗时任务逻辑,用户可在线体验Rolling Log等功能;

  • shardingJobHandler:分片示例任务,任务内部模拟处理分片参数,可参考熟悉分片任务;

  • commandJobHandler:通用命令行任务Handler;业务方只需要提供命令行即可;如 “pwd”命令;

  • httpJobHandler:通用HTTP任务Handler;业务方只需要提供HTTP链接等信息即可,不限制语言、平台。示例任务入参如下:

  url: http://www.xxx.com
  method: get 或 post
  data: post-data

分片任务示例

分片任务适用场景如:

  • 10个执行器的集群来处理10w条数据,每台机器只需要处理1w条数据,耗时降低10倍;

/**
 * 2、分片广播任务
 */
@XxlJob("shardingJobHandler")
public ReturnT<String> shardingJobHandler(String param) throws Exception {

    // 分片参数
    int shardIndex = XxlJobContext.getXxlJobContext().getShardIndex();
    int shardTotal = XxlJobContext.getXxlJobContext().getShardTotal();

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

    // 业务逻辑
    for (int i = 0; i < shardTotal; i++) {
        if (i == shardIndex) {
            XxlJobLogger.log("第 {} 片, 命中分片开始处理", i);
        } else {
            XxlJobLogger.log("第 {} 片, 忽略", i);
        }
    }

    return ReturnT.SUCCESS;
}

1、新增一个任务,使用 分片广播 策略。

1594812707068.jpg

2、开启两个执行器(修改端口号测试)

1594812762338.jpg

3、点击操作中的 执行一次,输入参数 200

4、执行日志结果,两个执行器,同时执行。

1594812773214.jpg

执行器1

2020-06-26 20:25:34 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-123] 
----------- xxl-job job execute start -----------
----------- Param:200
2020-06-26 20:25:34 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[61]-[Thread-123] 分片参数:当前分片序号 = 0, 总分片数 = 2
2020-06-26 20:25:34 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[66]-[Thread-123] 第 0 片, 命中分片开始处理
2020-06-26 20:25:34 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[68]-[Thread-123] 第 1 片, 忽略
2020-06-26 20:25:34 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-123] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-26 20:25:34 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

执行器2

                
2020-06-26 20:25:34 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-123] 
----------- xxl-job job execute start -----------
----------- Param:200
2020-06-26 20:25:34 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[61]-[Thread-123] 分片参数:当前分片序号 = 1, 总分片数 = 2
2020-06-26 20:25:34 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[68]-[Thread-123] 第 0 片, 忽略
2020-06-26 20:25:34 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[66]-[Thread-123] 第 1 片, 命中分片开始处理
2020-06-26 20:25:34 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-123] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-26 20:25:35 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

命令行任务测试

新增任务如下

1594812783060.jpg

执行一次参数:ls

执行任务结果

2020-06-27 01:12:29 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-125] 
----------- xxl-job job execute start -----------
----------- Param:ls
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] LICENSE
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] NOTICE
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] README.md
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] doc
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] log.path_IS_UNDEFINED
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] pom.xml
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] xxl-job-admin
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] xxl-job-core
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] xxl-job-executor-samples
2020-06-27 01:12:29 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#commandJobHandler]-[94]-[Thread-125] xxl-job.iml
2020-06-27 01:12:29 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-125] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-27 01:12:29 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

http 调用测试

url:http://httpbin.org/get
method:get

1594812792839.jpg

执行结果

2020-06-27 01:31:17 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-129] 
----------- xxl-job job execute start -----------
----------- Param:url:http://httpbin.org/get
method:get
2020-06-27 01:31:18 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#httpJobHandler]-[203]-[Thread-129] {  "args": {},   "headers": {    "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",     "Accept-Charset": "application/json;charset=UTF-8",     "Cache-Control": "no-cache",     "Content-Type": "application/json;charset=UTF-8",     "Host": "httpbin.org",     "Pragma": "no-cache",     "User-Agent": "Java/1.8.0_171",     "X-Amzn-Trace-Id": "Root=1-5ef630e6-d79302a562f91728db929449"  },   "origin": "221.218.27.251",   "url": "http://httpbin.org/get"}
2020-06-27 01:31:18 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-129] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-27 01:31:18 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

java 脚本测试

新增一条任务,选择 GLUE(Java)方式。

1594812803031.jpg

保存完成后,列表中操作按钮一栏,会多出 GLUE IDE 的按钮。

1594812813429.jpg

单击进入 IDE 编辑,默认脚本内容如下

1594812822860.jpg

稍作修改

package com.xxl.job.service.handler;

import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;

public class DemoGlueJobHandler extends IJobHandler {

    @Override
    public ReturnT<String> execute(String param) throws Exception {
        XxlJobLogger.log("XXL-JOB, Hello World,执行参数" + param);
        return ReturnT.SUCCESS;
    }

}

选择执行一次,查看日志结果(可自行修改脚本内容)。

1594812832721.jpg

执行结果

2020-06-27 01:43:03 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-123] 
----------- xxl-job job execute start -----------
----------- Param:程序喵
2020-06-27 01:43:03 [com.xxl.job.core.handler.impl.GlueJobHandler#execute]-[26]-[Thread-123] ----------- glue.version:1593193149000 -----------
2020-06-27 01:43:04 [sun.reflect.NativeMethodAccessorImpl#invoke0]-[-2]-[Thread-123] XXL-JOB, Hello World,执行参数程序喵
2020-06-27 01:43:04 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-123] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-27 01:43:04 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

python 脚本测试

新增一条任务,选 GLUE(python) 方式。

1594812842513.jpg

默认脚本内容如下

1594812852252.jpg

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
import sys

print "xxl-job: hello python"

print "脚本位置:", sys.argv[0]
print "任务参数:", sys.argv[1]
print "分片序号:", sys.argv[2]
print "分片总数:", sys.argv[3]

print "Good bye!"
exit(0)

执行日志

2020-06-27 00:19:59 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-130] 
----------- xxl-job job execute start -----------
----------- Param:程序喵
2020-06-27 00:19:59 [com.xxl.job.core.handler.impl.ScriptJobHandler#execute]-[80]-[Thread-130] ----------- script file:/Users/liurenkui/logs/xxl-job/jobhandler/gluesource/3_1593188362000.py -----------
xxl-job: hello python
脚本位置: /Users/liurenkui/logs/xxl-job/jobhandler/gluesource/3_1593188362000.py
任务参数: 程序喵
分片序号: 0
分片总数: 1
Good bye!
2020-06-27 00:19:59 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-130] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-27 00:19:59 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]

从日志看出IDE编辑的python脚本保存在了 3_1593188362000.py 文件中

shell 脚本测试

新增一条任务,选择 GLUE(Shell)方式。

与 Python模式相似,保存完成后,列表中操作按钮一栏,会多出 GLUE IDE 的按钮,默认脚本如下内容。

#!/bin/bash
echo "xxl-job: hello shell"

echo "脚本位置:$0"
echo "任务参数:$1"
echo "分片序号 = $2"
echo "分片总数 = $3"

echo "Good bye!"
exit 0

修改如下

#!/bin/bash
echo "xxl-job: 打印9*9乘法口诀。"

echo "脚本位置:$0"
echo "任务参数:$1"
echo "分片序号 = $2"
echo "分片总数 = $3"

echo -e "\n方法1\n"

awk 'BEGIN{for(n=0;n++<9;){for(i=0;i++<n;)printf i"x"n"="i*n" ";print ""}}'

echo -e "\n方法2\n"

for ((i=1;i<=9;i++)); do
   for ((j=1;j<=i;j++)); do
     result=$(($i*$j))
     echo -n "$j*$i=$result "
   done
   echo
done

echo "执行完成!"
exit 0

执行结果

2020-06-27 00:56:54 [com.xxl.job.core.thread.JobThread#run]-[127]-[Thread-133] 
----------- xxl-job job execute start -----------
----------- Param:程序喵
2020-06-27 00:56:54 [com.xxl.job.core.handler.impl.ScriptJobHandler#execute]-[80]-[Thread-133] ----------- script file:/Users/liurenkui/logs/xxl-job/jobhandler/gluesource/4_1593190411000.sh -----------
xxl-job: 打印9*9乘法口诀。
脚本位置:/Users/liurenkui/logs/xxl-job/jobhandler/gluesource/4_1593190411000.sh
任务参数:程序喵
分片序号 = 0
分片总数 = 1

方法1

1x1=1 
1x2=2 2x2=4 
1x3=3 2x3=6 3x3=9 
1x4=4 2x4=8 3x4=12 4x4=16 
1x5=5 2x5=10 3x5=15 4x5=20 5x5=25 
1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36 
1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49 
1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64 
1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81 

方法2

1*1=1 
1*2=2 2*2=4 
1*3=3 2*3=6 3*3=9 
1*4=4 2*4=8 3*4=12 4*4=16 
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81 
执行完成!
2020-06-27 00:56:54 [com.xxl.job.core.thread.JobThread#run]-[167]-[Thread-133] 
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-06-27 00:56:54 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[196]-[xxl-job, executor TriggerCallbackThread] 
----------- xxl-job job callback finish.

[Load Log Finish]


未经允许请勿转载:程序喵 » 分布式任务调度平台 XXL-JOB 快速入门使用

点  赞 (3) 打  赏
分享到: