一、分布式任务调度概述
1、什么是任务调度平台
任务调度是指基于给定的时间点,给定的时间间隔又或者给定执行次数自动的执行任务。我们可以思考一下在以下场景中,我们应该怎么实现:
支付系统每天凌晨 1 点,进行一天清算,每月 1 号进行上个月清算;
电商整点抢购,商品价格8点整开始优惠
12306 购票系统,超过 30 分钟没有成功支付订单的,进行回收处理
2、为什么需要任务调度平台
定时任务是程序员不可避免的话题,很多业务场景需要我们某一特定的时刻去做某件任务。一般来说,系统可以使用消息传递代替部分定时任务(比如商品成功发货后,需要向客户发送短信提醒),两者有很多相似之处,一些场景下也可以相互替换,但是有一些不能:
时间驱动
/事件驱动
:内部系统一般可以通过事件来驱动,但如果涉及到外部系统,则只能使用时间驱动。如爬取外部网站价格,每小时爬一次。批量处理
/逐条处理
:批量处理堆积的数据更加高效,在不需要实时性的情况下比消息中间件更有优势。而且有的业务逻辑只能批量处理,如移动每个月结算我们的花费。实时性
/非实时性
:消息中间件能够做到实时处理数据,但是有些情况下并不需要实时,比如:vip 升级。系统内部
/系统解耦
:定时任务调度一般是在系统内部,而消息中间件可用于两个系统间
并且对于分布式系统来说,如果处理不当,会存在同一系统不同节点之间定时任务相互影响的问题,再考虑上监控、日志、信息面板,加上不同系统之间管理维护的问题,自己实现一套的成本又上来了..所以我们可以考虑一些比较成熟的任务调度平台来使用
3、任务调度框架选型
Java 领域主要分布式调度系统如下:
xxl-job
:是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展 。Elastic-Job
:当当开源的分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite
和Elastic-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
第二步:初始化数据库
找到 /xxl-job/doc/db/table_xxl_job.sql
初始化 SQL 脚本,将此脚本在MySQL数据库中执行一遍。
执行完毕,会在MySQL数据库中生成如下 8 张表:
第三步:配置并启动 "调度中心"
调度中心配置文件地址:/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
",登录后运行界面如下图所示:
至此,「调度中心」项目已经部署成功了,调度中心集群(可选)配置可参考官方文档。
第四步:配置启动"执行器"
执行器配置,配置文件地址:/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
了。
第五步:执行一个任务
在“第二步:初始化数据库” 已经初始化了一个任务。
如上图,对应代码位置:/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
是递增执行。
单机操作中的 查看日志
观察执行结果。
第六步:开发第一个任务
经过测试的任务之后,开发一个自己的任务测试。
当「调度中心
」和「执行器
」都启动之后,我们可以直接在「调度中心
」的任务管理界面新增一条配置如下图所示(参考)的任务:
任务详解
执行器
:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;任务描述
:任务的描述信息,便于任务管理;路由策略
:当执行器集群部署时,提供丰富的路由策略,包括;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、新增一个任务,使用 分片广播
策略。
2、开启两个执行器(修改端口号测试)
3、点击操作中的 执行一次
,输入参数 200
。
4、执行日志结果,两个执行器,同时执行。
执行器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]
命令行任务测试
新增任务如下
执行一次参数: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
执行结果
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)
方式。
保存完成后,列表中操作按钮一栏,会多出 GLUE IDE
的按钮。
单击进入 IDE 编辑,默认脚本内容如下
稍作修改
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; } }
选择执行一次
,查看日志结果(可自行修改脚本内容)。
执行结果
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)
方式。
默认脚本内容如下
#!/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 快速入门使用