简介
XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
选型
框架对比(前人总结)
feature | quartz | elastic-job-cloud | xxl-job | antares | opencron |
---|---|---|---|---|---|
依赖 | mysql | jdk1.7+, zookeeper 3.4.6+ ,maven3.0.4+ ,mesos | mysql ,jdk1.7+ , maven3.0+ | jdk 1.7+ , redis , zookeeper | jdk1.7+ , Tomcat8.0+ |
HA | 多节点部署,通过竞争数据库锁来保证只有一个节点执行任务 | 通过zookeeper的注册与发现,可以动态的添加服务器。支持水平扩容 | 集群部署 | 集群部署 | — |
任务分片 | — | 支持 | 支持 | 支持 | — |
文档完善 | 完善 | 完善 | 完善 | 文档略少 | 文档略少 |
管理界面 | 无 | 支持 | 支持 | 支持 | 支持 |
难易程度 | 简单 | 较复杂 | 简单 | 一般 | 一般 |
公司 | OpenSymphony | 当当网 | 个人 | 个人 | 个人 |
高级功能 | — | 弹性扩容,多种作业模式,失效转移,运行状态收集,多线程处理数据,幂等性,容错处理,spring命名空间支持 | 弹性扩容,分片广播,故障转移,Rolling实时日志,GLUE(支持在线编辑代码,免发布),任务进度监控,任务依赖,数据加密,邮件报警,运行报表,国际化 | 任务分片, 失效转移,弹性扩容 , | 时间规则支持quartz和crontab ,kill任务, 现场执行,查询任务运行状态 |
缺点 | 没有管理界面,以及不支持任务分片等。不适用于分布式场景 | 需要引入zookeeper , mesos, 增加系统复杂度, 学习成本较高 | 调度中心通过获取 DB锁来保证集群中执行任务的唯一性, 如果短任务很多,随着调度中心集群数量增加,那么数据库的锁竞争会比较厉害,性能不好。 | 不支持动态添加任务 | 不适用于分布式场景 |
使用企业 | 大众化产品,对分布式调度要求不高的公司大面积使用 | 36氪,当当网,国美,金柚网,联想,唯品会,亚信,平安,猪八戒 | 大众点评,运满满,优信二手车,拍拍贷 | — | — |
从上述对比来看,XXL-JOB简单、依赖少、文档完善、社区活跃,是个不错的选择。
架构
官方的架构图,一共就两大组件
调度中心——xxl-job-admin,有porta界面,可以管理控制所有的任务执行情况
执行器——需要业务方自行开发接入的,将任务托管给调度中心进行控制
安装部署
从github把源码工程clone到本地 https://github.com/xuxueli/xxl-job
部署起来非常简单
调度中心
修改xxl-job-admin的配置文件,数据地址等修改成自己的,mvn clean package打包,传到服务器上部署启动
执行器
参照官方示例编写自己的业务逻辑,配置好相关配置属性,可参照 https://github.com/cwtree/cube-xxl-job-executor.git
常规任务
@XxlJob("myJobHandler")
public void myJobHandler() throws Exception {
XxlJobHelper.log("job test ...");
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
log.info("常规任务执行。。。");
}
分片任务
@XxlJob("shardJobHandler")
public void shard() throws Exception {
// 分片参数
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
XxlJobHelper.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
log.info("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
// 业务逻辑
for (int i = 0; i < shardTotal; i++) {
if (i == shardIndex) {
XxlJobHelper.log("第 {} 片, 命中分片开始处理", i);
log.info("第 {} 片, 命中分片开始处理", i);
} else {
XxlJobHelper.log("第 {} 片, 忽略", i);
log.info("第 {} 片, 忽略", i);
}
}
log.info("分片任务执行。。。");
}
执行器启动后,就可以去调度中心新增任务,新增执行器管控起来了
分片任务使用场景:
订单超时场景,部署了10个进程执行器,业务逻辑是查询快要超时的订单,然后修改订单状态关闭,如果快要超时的订单过多,靠一个进程执行任务来做,可能内存溢出或超时等,此时需要将订单数据分片分到各个进程执行器里,分担执行,提高效率。