分布式任务调度之xxl-job
1.分布式任务调度的背景
无论是互联网应用或者企业级应用,都充斥着大量的批处理任务。我们常常需要一些任务调度系统帮助我们解决问题。随着微服务化架构的逐步演进,单体架构逐渐演变为分布式、微服务架构。在此的背景下,很多原先的任务调度平台已经不能满足业务系统的需求。于是出现了一些基于分布式的任务调度平台
1.1.分布式任务调度的演变
在实际业务开发过程中,很多时候我们无可避免的需要使用一些定时任务来解决问题。通常我们会有多种解决方案:例如Quartz,还有spring框架自带的spring-task以及springboot自带的schedule (当然这种情况可能机器很少而且任务简单又不是很多的情况下)。然而,当我们应用复杂度升高,定时任务数量增多且任务之间产生依赖关系时,用上面的进行定时任务管理配置,就会非常混乱,严重影响工作效率。这时候就会产生一系列问题:
1. 任务管理混乱,生命周期无法统一协调管理;
2. 任务之间如果存在依赖关系,难以编排;
随着互联网的发展,分布式服务架构势越来越流行。相应也需要一个分布式任务调度系统来管理分布式架构中的定时任务。
1.2.分布式任务调度的优势
在分布式服务架构的基础上,由于独立业务的数量可能很多,此时如果定时任务单独在该服务中实现,很可能会出现难以管理的情况,且避免不了由于定时任务的更改而导致的业务重启。因此,一个独立的分布式任务调度系统是很必要的,可以用来全局统筹管理所有的定时任务。同时,将任务的配置单独抽离出来,作为该分布式任务调度系统的功能,就能做到定时任务的更改不影响任何业务,也不影响整个系统:
① 通过调度与任务分离的方式进行管理,大大降低了开发和维护成本;
② 分布式部署,保证了系统的高可用性,伸缩性,负载均衡,提高了容错性;
③ 可以通过控制台部署和管理定时任务,方便灵活高效;
④ 任务都可以持久化到数据库,避免了宕机和数据丢失带来的隐患,同时有完善的任务失败重做机制和详细的任务跟踪及告警策略
2.分布式调度任务框架介绍
2.1.Elastic-Job
Elastic Job是当当网架构师开发,是一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成;定位为轻量级无中心化解决方案,使用 jar 包的形式提供分布式任务的协调服务。支持分布式调度协调、弹性扩容缩容、失效转移、错过执行作业重触发、并行调度、自诊断和修复等等功能特性
2.2.TBSchedule
阿里早期开源的分布式任务调度系统。代码略陈旧,使用timer而非线程池执行任务调度。众所周知,timer在处理异常状况时是有缺陷的。而且TBSchedule作业类型较为单一,只能是获取/处理数据一种模式。而且文档缺失比较严重,还有就是要依赖Zookeeper
2.3.sia-task
SIA是Simple is Awesome的简称,SIA-TASK(微服务任务调度平台)是其中的一项重要产品,SIA-TASK契合当前微服务架构模式,具有跨平台,可编排,高可用,无侵入,一致性,异步并行,动态扩展,实时监控等特点,也要依赖Zookeeper,更偏向于解决任务编排和跨平台
2.4.xxl-job
xxl-job是大众点评员工徐雪里于2015年发布的分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用
2.5.对比图
|
任务编排 |
任务分片 |
跨平台 |
高可用 |
故障转移 |
实时监控 |
Quartz |
× |
× |
.net |
√ |
× |
Api监控 |
Elastic-Job |
× |
√ |
× |
√ |
√ |
√ |
TBSchedule |
× |
√ |
× |
√ |
√ |
√ |
sia-task |
√ |
√ |
√ |
√ |
√ |
√ |
xxl-job |
子任务依赖 |
√ |
× |
√ |
√ |
√ |
综上,更倾向于选择xxl-job:
a. 轻量级,支持通过Web页面对任务进行动态CRUD操作,操作简单
b. 只依赖数据库作为集群注册中心,接入开发简单,不需要ZK
c. 高可用、解耦、高性能、监控报警、分片、重试、故障转移
d. 团队持续开发,社区活跃
e. 支持后台直接查看每个任务执行实时日志
3. xxl-job
3.1.特性
1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;
2、动态:支持动态修改任务状态、启动/停止任务,以及终止运行中任务,即时生效;
3、调度中心HA(中心式):调度采用中心式设计,“调度中心”自研调度组件并支持集群部署,可保证调度中心HA;
4、执行器HA(分布式):任务分布式执行,任务"执行器"支持集群部署,可保证任务执行HA;
5、注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
6、弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
7、触发策略:提供丰富的任务触发策略,包括:Cron触发、固定间隔触发、固定延时触发、API(事件)触发、人工触发、父子任务触发;
8、调度过期策略:调度中心错过调度时间的补偿处理策略,包括:忽略、立即补偿触发一次等;
9、阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
10、任务超时控制:支持自定义任务超时时间,任务运行超时将会主动中断任务;
详情见:https://gitee.com/xuxueli0323/xxl-job
3.2.架构设计图
3.3.入门案例
3.3.1.下载源码
请下载项目源码并解压,使用IDEA工具导入项目
项目结构图如下:
3.3.2.初始化调度数据库
请下载项目源码并解压,获取 "调度数据库初始化SQL脚本" 并执行即可。
"调度数据库初始化SQL脚本" 位置为:/xxl-job/doc/db/tables_xxl_job.sql
xxl_job_lock:任务调度锁表;
xxl_job_group:执行器信息表,维护任务执行器信息;
xxl_job_info:调度扩展信息表:用于保存XXL-JOB调度任务的扩展信息,如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等;
xxl_job_log:调度日志表:用于保存XXL-JOB任务调度的历史信息,如调度结果、执行结果、调度入参、调度机器和执行器等等;
xxl_job_log_report:调度日志报表:用户存储XXL-JOB任务调度日志的报表,调度中心报表功能页面会用到;
xxl_job_logglue:任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能;
xxl_job_registry:执行器注册表,维护在线的执行器和调度中心机器地址信息;
xxl_job_user:系统用户表;
3.3.3.配置启动调度中心
调度中心配置文件地址:/xxl-job/xxl-job-admin/src/main/resources/application.properties
调度中心配置内容说明:
### 调度中心JDBC链接:链接地址请保持和 2.1章节所创建的调度数据库的地址一致 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai 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
### 调度中心通讯TOKEN [选填]:非空时启用; xxl.job.accessToken=
### 调度中心国际化配置 [必填]:默认为 "zh_CN"/中文简体, 可选范围为"zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文; xxl.job.i18n=zh_CN
## 调度线程池最大线程配置【必填】 xxl.job.triggerpool.fast.max=200 xxl.job.triggerpool.slow.max=100
### 调度中心日志表数据保存天数 [必填]:过期日志自动清理;限制大于等于7时生效,否则, 如-1,关闭自动清理功能; xxl.job.logretentiondays=30 |
启动类XxlJobAdminApplication执行
调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址)
默认登录账号 "admin/123456", 登录后运行界面如下图所示
至此“调度中心”项目已经启动成功
3.3.4.配置启动执行器
执行器配置,配置文件地址:
/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
### 执行器通讯TOKEN [选填]:非空时启用; xxl.job.accessToken=
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册 xxl.job.executor.appname=xxl-job-executor-sample ### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。 xxl.job.executor.address= ### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"; xxl.job.executor.ip= ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口; xxl.job.executor.port=9999 ### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径; xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler ### 执行器日志文件保存天数 [选填] :过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能; xxl.job.executor.logretentiondays=30 |
启动类XxlJobExecutorApplication执行
至此“执行器”项目已经启动成功
3.3.5.开发第一个任务”Hello World”
本示例以新建一个 “GLUE模式(Java)” 运行模式的任务为例。更多有关任务的详细配置,请查看“章节三:任务详解”。( “GLUE模式(Java)”的执行代码托管到调度中心在线维护,相比“Bean模式任务”需要在执行器项目开发部署上线,更加简便轻量)
前提:请确认“调度中心”和“执行器”项目已经成功部署并启动;
步骤一:新建任务:
登录调度中心,点击下图所示“新建任务”按钮,新建示例任务。然后,参考下面截图中任务的参数配置,点击保存。
步骤二:触发执行
请点击任务右侧 “执行” 按钮,可手动触发一次任务执行(通常情况下,通过配置Cron表达式进行任务调度触发)。
步骤三:查看日志:
请点击任务右侧 “日志” 按钮,可前往任务日志界面查看任务日志。 在任务日志界面中,可查看该任务的历史调度记录以及每一次调度的任务调度信息、执行参数和执行信息。运行中的任务点击右侧的“执行日志”按钮,可进入日志控制台查看实时执行日志。