日志

一文读懂分布式任务调度平台XXL-JOB

 来源    2019-10-09    1  

本文主要介绍分布式任务调度平台XXL-JOB(v2.1.0版本),包括功能特性、实现原理、优缺点、同类框架比较等

基本介绍

项目开发中,常常以下场景需要分布式任务调度:

  • 同一服务多个实例的任务存在互斥时,需要统一协调
  • 定时任务的执行需要支持高可用、监控运维、故障告警
  • 需要统一管理和追踪各个服务节点定时任务的运行情况,以及任务属性信息,例如任务所属服务、所属责任人

因此,XXL-JOB应运而生:
XXL-JOB是一个开源的轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展、开箱即用,其中“XXL”是主要作者,大众点评许雪里名字的缩写

自2015年开源以来,已接入数百家公司的线上产品线,接入场景涉及电商业务,O2O业务和大数据作业等

功能特性

主要功能特性如下:

  • 简单灵活
    提供Web页面对任务进行管理,管理系统支持用户管理、权限控制;
    支持容器部署;
    支持通过通用HTTP提供跨平台任务调度;

  • 丰富的任务管理功能
    支持页面对任务CRUD操作;
    支持在页面编写脚本任务、命令行任务、Java代码任务并执行;
    支持任务级联编排,父任务执行结束后触发子任务执行;
    支持设置任务优先级;
    支持设置指定任务执行节点路由策略,包括轮询、随机、广播、故障转移、忙碌转移等;
    支持Cron方式、任务依赖、调度中心API接口方式触发任务执行

  • 高性能
    调度中心基于线程池多线程触发调度任务,快任务、慢任务基于线程池隔离调度,提供系统性能和稳定性;
    任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰;

  • 高可用
    任务调度中心、任务执行节点均 集群部署,支持动态扩展、故障转移
    支持任务配置路由故障转移策略,执行器节点不可用是自动转移到其他节点执行
    支持任务超时控制、失败重试配置
    支持任务处理阻塞策略:调度当任务执行节点忙碌时来不及执行任务的处理策略,包括:串行、抛弃、覆盖策略

  • 易于监控运维
    支持设置任务失败邮件告警,预留接口支持短信、钉钉告警;
    支持实时查看任务执行运行数据统计图表、任务进度监控数据、任务完整执行日志;

系统设计

1 设计思路

将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求;
将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑;
因此,“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性;

2 系统组成

  • 调度模块(调度中心): 负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块; 支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover

  • 执行模块(执行器): 负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效; 接收“调度中心”的执行请求、终止请求和日志请求等

3 工作原理

  • 任务执行器根据配置的调度中心的地址,自动注册到调度中心
  • 达到任务触发条件,调度中心下发任务
  • 执行器基于线程池执行任务,并把执行结果放入内存队列中、把执行日志写入日志文件中
  • 执行器的回调线程消费内存队列中的执行结果,主动上报给调度中心
  • 当用户在调度中心查看任务日志,调度中心请求任务执行器,任务执行器读取任务日志文件并返回日志详情

4 HA设计

4.1 调度中心高可用

调度中心支持多节点部署,基于数据库行锁保证同时只有一个调度中心节点触发任务调度,参考com.xxl.job.admin.core.thread.JobScheduleHelper#start

Connection conn = XxlJobAdminConfig.getAdminConfig().getDataSource().getConnection();
connAutoCommit = conn.getAutoCommit();
conn.setAutoCommit(false);
preparedStatement = conn.prepareStatement(  "select * from xxl_job_lock where lock_name = 'schedule_lock' for update" );
preparedStatement.execute();

# 触发任务调度

# 事务提交
 conn.commit();

4.2 任务调度高可用

  • 路由策略
    调度中心基于路由策略路由选择一个执行器节点执行任务,XXL-JOB提供了如下路由策略保证任务调度高可用:
    忙碌转移策略: 下发任务前向执行器节点发起rpc心跳请求查询是否忙碌,如果执行器节点返回忙碌则转移到其他执行器节点执行(参考 com.xxl.job.admin.core.route.strategy.ExecutorRouteBusyover)
    故障转移策略: 下发任务前向执行器节点发起rpc心跳请求查询是否在线,如果执行器节点没返回或者返回不可用则转移到其他执行器节点执行 (参考com.xxl.job.admin.core.route.strategy.ExecutorRouteFailover)

  • 阻塞处理策略
    当执行器节点存在多个相同任务id的任务未执行完成,则需要基于阻塞策略对任务进行取舍:
    串行策略:默认策略,任务进行排队、丢弃旧任务策略丢弃新任务策略
    (参考:com.xxl.job.core.biz.impl.ExecutorBizImpl#run)

同类框架比较

特性 quartz elastic-job-lite xxl-job LTS
依赖 MySQL、jdk jdk、zookeeper mysql、jdk jdk、zookeeper、maven
高可用 多节点部署,通过竞争数据库锁来保证只有一个节点执行任务 通过zookeeper的注册与发现,可以动态的添加服务器 基于竞争数据库锁保证只有一个节点执行任务,支持水平扩容。可以手动增加定时任务,启动和暂停任务,有监控 集群部署,可以动态的添加服务器。可以手动增加定时任务,启动和暂停任务。有监控
任务分片 ×
管理界面 ×
难易程度 简单 简单 简单 略复杂
高级功能 - 弹性扩容,多种作业模式,失效转移,运行状态收集,多线程处理数据,幂等性,容错处理,spring命名空间支持 弹性扩容,分片广播,故障转移,Rolling实时日志,GLUE(支持在线编辑代码,免发布),任务进度监控,任务依赖,数据加密,邮件报警,运行报表,国际化 支持spring,spring boot,业务日志记录器,SPI扩展支持,故障转移,节点监控,多样化任务执行结果支持,FailStore容错,动态扩容。
版本更新 半年没更新 2年没更新 最近有更新 1年没更新

使用

快速上手

具体如何快速上手使用,官方文档:http://www.xuxueli.com/xxl-job/ 已经介绍得比较详细和清楚,不再赘述

注意事项

  • 1 时钟同步问题
    调度中心和任务执行器需要时间同步,同步时间误差需要在3分钟内,否则抛出异常
    参考:com.xxl.rpc.remoting.provider.XxlRpcProviderFactory#invokeService
if (System.currentTimeMillis() - xxlRpcRequest.getCreateMillisTime() > 3*60*1000) {
    xxlRpcResponse.setErrorMsg("The timestamp difference between admin and executor exceeds the limit.");
    return xxlRpcResponse;
}
  • 2 时区问题
    任务由调度中心触发,按照在调度中心设置任务的cron表达式触发时,需要注意部署调度中心的机器所在的时区,按照该时区定制化cron表达式

  • 3 任务执行中服务宕掉问题
    调度中心完成任务下发,执行器在执行任务的过程中,如果执行器突然服务宕掉,会导致任务的执行问题在调度中心是执行中,调度中心并不会发起失败重试。即使任务设置了超时时间,执行器宕掉导致导致任务长时间未执行完成,调度中心界面也不会看到任务超时,因为任务超时是由执行器检测的并上报给调度中心的

因此遇到任务长时间未执行完成,可以关注是否发生了执行器突然服务宕掉

  • 4 优雅停机问题
    执行器执行任务基于线程池异步执行,当需要重启时需要注意线程池中还有未执行完成任务的问题,需要优雅停机,可以直接基于XxlJobExecutor.destroy()优雅停机,注意该方法在v2.0.2之前的版本存在bug导致无法优雅停机,v2.0.2及之后的版本才修复(参考:https://github.com/xuxueli/xxl-job/issues/727)

  • 5 失败重试问题
    当执行器节点部分服务不可用,例如节点磁盘损坏,但在调度中心仍然处于在线时,调度中心仍可能基于路由策略(包括故障转移策略)路由到该未下线的节点,并不断重试,不断失败,导致重试次数耗尽。所以路由策略尽量不要采用固定化策略,例如固定第一个、固定最后一个

总结

XXL-JOB上手还是比较简单,项目源码还是比较整洁,容易读懂,学习之后可以更加深入理解分布式系统设计、网络通信、多线程协同处理等知识点,推荐阅读​

参考

XXL-JOB github仓库
XXL-JOB 官方文档

分布式任务调度平台 – antares
日志分布式任务调度平台(Distributed Job Schedule Platform) Antares特性 基于Quartz的分布式调度 一个任务仅会被服务器集群中的某个节点调度,调度机制基于成熟的 ...
一文读懂 Android TouchEvent 事件分发、拦截、处理过程
日志什么是事件?事件是用户触摸手机屏幕,引起的一系列TouchEvent,包括ACTION_DOWN.ACTION_MOVE.ACTION_UP.ACTION_CANCEL等,这些action组合后变成点 ...
一文读懂类加载机制
日志类记载过程 多个java文件经过编译打包生成可运行的jar包,最终由java命令运行某个主类的main函数启动程序,这里首先需要通过类加载器把主类加载到jvm. 主类在运行过程中如果使用到其他类,会逐 ...
干货|一文读懂 Spring Data Jpa!
日志有很多读者留言希望松哥能好好聊聊 Spring Data Jpa!其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring D ...
夯实Java基础系列7:一文读懂Java 代码块和执行顺序
日志目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...
Distributed 分布式任务调度平台
日志一.概述 什么是定时任务 二.Java实现定时任务方式 2.1 Thread 2.2 TimerTask 2.3 ScheduledExecutorService 2.4 Quartz 引入maven ...
分布式任务调度平台XXL-JOB搭建教程
日志关于分布式任务调度平台XXL-JOB,其实作者 许雪里在其发布的中文教程中已经介绍的很清楚了,这里我就不做过多的介绍了,关于其搭建教程,本人依照其文档搭建起来基本上也没遇到啥问题,这里通过博客的形式记 ...
一文读懂Asp.net core 依赖注入(Dependency injection)
日志一.什么是依赖注入 首先在Asp.net core中是支持依赖注入软件设计模式,或者说依赖注入是asp.net core的核心: 依赖注入(DI)和控制反转(IOC)基本是一个意思,因为说起来谁都离不 ...
宜信开源|分布式任务调度平台SIA-TASK的架构设计与运行流程
日志一.分布式任务调度的背景 无论是互联网应用或者企业级应用,都充斥着大量的批处理任务.我们常常需要一些任务调度系统来帮助解决问题.随着微服务化架构的逐步演进,单体架构逐渐演变为分布式.微服务架构.在此背 ...
分布式任务调度平台XXL-Job集群版搭建
日志如果集群:  保存后: 启动两个 job 第二个job的配置: # web port server.port=8082 # log config logging.config=classpath:lo ...
分布式任务调度平台XXL-JOB
日志<分布式任务调度平台XXL-JOB>        一.简介 1.1 概述 XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码 ...
一文读懂机器学习,大数据/自然语言处理/算法全有了……
日志原文地址 http://www.open-open.com/lib/view/open1420615208000.html http://www.cnblogs.com/subconscious/p/ ...
一文读懂DDD
日志原文:一文读懂DDD何为DDD DDD不是架构设计方法,不能把每个设计细节具象化,DDD是一套体系,决定了其开放性,体系中可以用任何一种方法来解决这些问题,但是如果一些关键问题没有具体方案落地,可能让 ...
XXL-JOB分布式任务调度平台安装与部署
日志配XXL-JOB分布式任务调度平台安装与部署 一.简介 XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并接入多家公司线上产品线,开箱即 ...
[转帖]一篇读懂分布式架构下的负载均衡
日志一篇读懂分布式架构下的负载均衡 http://developer.51cto.com/art/201905/596022.htm 其实 负载均衡真应该好好看看 包括 k8s 里面的 nigress 还 ...
转帖 一文读懂电影《流浪地球》没有交代清楚的烧脑科学知识
日志一文读懂电影<流浪地球>没有交代清楚的烧脑科学知识 https://www.huxiu.com/article/283864.html 本文转载自微信公众号“腾讯科技”(ID:qqtech ...
一文弄懂“分布式锁”
日志多线程情况下对共享资源的操作需要加锁,避免数据被写乱,在分布式系统中,这个问题也是存在的,此时就需要一个分布式锁服务.常见的分布式锁实现一般是基于DB.Redis.zookeeper.下面笔者会按照顺 ...
一文读懂消息队列一些设计
日志高可用 常用的消息队列的高可用是怎么设计的呢? 消息队列一般都有一个nameserver服务,用来检测broker是否存活,或者处理能力上是否存在延迟.这样在发送消息时就可以规避将消息发送到宕机的br ...
一文读懂架构师都不知道的isinstance检查机制
日志起步 通过内建方法 isinstance(object, classinfo) 可以判断一个对象是否是某个类的实例.但你是否想过关于鸭子协议的对象是如何进行判断的呢? 比如 list 类的父类是继 o ...