一 背景介绍
对于现在的企业应用来说,不管是写在 Linux 系统 Crontab 中的定时任务,还是写在业务系统中的定时跑批,我们总会需要一些任务调度系统帮助我们解决问题。
随着微服务化架构的逐步演进,应用逐渐由单点转向分布式协作。在分布式的背景下,单点的任务调度显然不能满足需求,于是出现了一些分布式任务调度框架。这些框架各有其特点,但仍然有不足之处,比如不支持任务编排、与业务高耦合、不支持跨平台等问题。对于调度作业的开发,由于任务编排和业务逻辑耦合,不利于系统的维护和开发,健壮的调度任务管理已经是非常重要的一环。
我们调研了市场上主流的开源分布式任务调度框架,针对公司的实际需求,使用公司内部推广的 SpringCloud 技术栈,由统一开发平台小组孵化一套分布式调度框架(Skyworld-Task)。与大多数分布式任务调度框架不同,Skyworld-Task 注重点在任务编排,而不仅仅是任务调度。Skyworld-Task 具有跨平台,可编排,高可用,无侵入,一致性,异步并行,动态扩展,实时监控等特点。
二 为什么要用分布式任务调度框架
2-1分布式调度演进
在实际业务开发过程中,很多时候我们无可避免的需要使用一些定时任务来解决问题。通常我们会有多种解决方案:使用Crontab或SpringCron(当然这种情况可能机器很少而且任务简单又不是很多的情况下),但是当我们应用复杂度升高,定时任务数量增多且任务之间产生依赖关系,Crontab进行定时任务的管理配置,就会非常混乱,严重影响工作效率。这时候就会产生一系列问题需要我们去解决:
• 每个服务器各个用户下的任务管理混乱,生命周期无法统一协调管理;
• 定时任务运行异常告警难以统一对接;
• 任务之间如果存在依赖关系,很难进行多次编排;
• 随着时间增长,当定时任务数量很多的时候,定时任务就非常难以管理,线上跑了多个定时任务,每个定时任务什么时候运行等问题变得很难解决。
或许我们可以尝试使用单点定时任务来解决上述问题,但是单点定时任务也会给我们带来一些额外的问题,比如:
• 功能相对简单,交互性差,任务部署效率低,开发和维护成本比较高,不能很好的满足各系统定时任务的管理和控制,尤其在多系统的环境下更加明显;
• 单机部署,可靠性差;
随着互联网的发展,应用服务中的定时任务数量日益增加,常规的垂直应用架构已无法应对,分布式服务架构势在必行,同时,也需要一个分布式任务调度系统来管理分布式服务中的定时任务 ,所以分布式任务调度系统也就应用而生。
2-2分布式调度架构
分布式任务调度设计
当垂直应用越来越多,应用之间交互也会越来越复杂,通常我们采用分布式或者微服务架构,将核心业务抽取出来,形成单独的服务,一个独立的微服务群体逐渐形成稳定的服务中心,使得业务应用能更快地响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架成为关键,同时,由于服务独立,一般能做到定时任务独立的情况,因此,任务的更改对于整体系统的影响小之又小。通常我们会采用任务与调度分离的方式(如上图所示),任务的执行逻辑无需关注调度与编排,同时可以保证执行器和调度的高可用,易于开发和维护。
2-3 分布式任务调度优势
在分布式服务架构的基础上,由于独立业务的数量可能很多,此时如果定时任务单独在该服务中实现,很可能会出现难以管理的情况,且避免不了定时任务更改导致的业务重启。因此,一个独立的分布式任务调度系统是很必要的,可以用来全局统筹管理所有的定时任务。同时,将任务的配置单独抽离出来,作为该分布式任务调度系统的功能,就能做到定时任务的更改不影响任何业务,也不影响整个系统:
• 通过调度与任务分离的方式进行管理,大大降低了开发和维护成本;
• 分布式部署,保证了系统的高可用性,伸缩性,负载均衡,提高了容错性;
• 可以通过控制台部署和管理定时任务,方便灵活高效;
• 任务都可以持久化到数据库,避免了宕机和数据丢失带来的隐患,同时有完善的任务失败重做机制和详细的任务跟踪及告警策略。
三 Skyworld-Task调度框架技术选型
3.1 分析分布式定时任务考虑的设计要素:
设计图
3.2 考虑公司业务需求
我们与相关业务部门开展了多次需求讨论,进行了深入交流。整理的主要需求如下:
• 任务编排:多个业务之间的定时任务有些存在流程次序;
• 任务分片:对于一个大型任务,需要分片并行执行;
• 跨平台:除了使用Java技术栈(SpringBoot、Spring等)的项目之外,还有其他语言的应用;
• 无侵入:业务不希望与调度高耦合,只关注业务的执行逻辑;
• 故障转移:任务执行过程中遇到问题有补偿措施,减少人工介入;
• 高可用:调度系统自身必须保证高可用;
• 实时监控:实时获取任务的执行状态;
• 可视化:任务调度的操作提供可视化页面,方便使用;
• 动态编辑:业务的任务时钟参数可能变动,不希望停机部署。
3.3 Skyworld-Task技术选型
下面我们先对比市场上主流的开源分布式任务调度框架,分析其优缺点,然后再说我们的设计框架。
• Quartz
Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。相比于 JDK 或 Spring 提供的定时任务,Quartz 对单个任务的控制基本做到了极致,以其强大功能和应用灵活性,在企业应用中发挥了巨大的作用。然而 Quartz 并不支持任务的编排(任务之间有依赖),而且不支持任务分片。
• TBSchedule
TBSchedule是一个支持分布式的调度框架,能让一种批量任务或者不断变化的任务,被动态的分配到多个主机的JVM中,不同的线程组中并行执行。基于Zookeeper的纯Java实现,由Alibaba开源。TBSchedule侧重于任务的分发,支持任务分片,但是没有任务编排,也不是跨平台的。
• Elastic-Job
Elastic-Job 是当当开源的一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。Elastic-Job支持任务分片(作业分片一致性),但是没有任务编排,也不是跨平台的。
• Saturn
Saturn 是唯品会开源的分布式,高可用的调度服务。Saturn 在 Elastic-Job 做二次开发,支持监控,任务分片,跨平台,但是没有任务编排。
• Antares
Antares 是基于Quartz的分布式调度,支持分片,支持树形任务依赖,但是不是跨平台的。
• Uncode-Schedule
Uncode-Schedule 是基于Zookeeper的分布式任务调度组件。支持所有任务在集群中不重复,不遗漏的执行。但是不支持任务分片,也没有任务编排,还不是跨平台的。
• XXL-JOB
XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。XXL-JOB支持分片,简单支持任务依赖,支持子任务依赖,不是跨平的。
对比下Skyworld-Task与这些任务调度框架:
可以发现,这些调度框架基本上都支持高可用、故障转移与实时监控等功能,但是对于任务编排、任务分片与跨平台等功能的支持各有侧重点。这里 Skyworld-Task 将全面支持这些功能。Skyworld-Task 所采用的技术和相关中间件如下:
• REST:一种软件架构风格。这里要求执行器暴露 HTTP 调用接口来达到跨平台的目的;
• SpringBoot:社区活跃的开发框架,也是公司指定的统一开发框架。用于快速开发,快速迭代;
• Zookeeper:久经考验的注册中心。用来解决调度中心高可用,分布式一致性等问题;
• Quartz:功能强大,应用灵活,对单个任务的控制基本做到了极致。这里用来作为调度中心时钟组件;
• Redis:高速缓存。用来存储鉴权所需的数据;
• MySQL:用于元数据存储与(暂时)日志存取;
• RabbitMQ:安全可靠的消息中间件。用于处理任务调用失败时的补偿逻辑;
• AOP:切面编程技术。在Spring项目扩展包Hunter中使用,保证Task被串行调用(单例单线程)。
3.4 简要概述
基于Zookeeper+Quartz的分布式任务调度组件,设计复杂度低,使用极为简单,Task开发时只需要引入jar包,无需额外的维护调度栈,调度和任务分离。而且定时任务的实现方式和原始的Http接口保持一致,所以普通的定时任务改造成分布式很方便。
四 Skyworld-Task架构与设计
4.1 系统组成
分布式调度框架(Skyworld-Task)采用任务和调度分离的方式,业务的执行任务逻辑和调度逻辑完全分离;
系统组成共涉及一下几个核心概念:
• Task: 业务任务的最小执行单元,指执行器对外暴露的调用接口,由业务发布。用来执行业务逻辑,完成特定的功能;
• Job:是一个完整的任务执行单元,调度(schedule)的最小单位。Job中包含多个Task。各个Task之间可能有相互依赖关系,需要按照一定次序调用;
• Scheduler: 调度中心,平台自身并不承担业务逻辑,调度中心负责发起调度请求;
• Config: 编排中心 负责任务的创建、录入、编排;展示。给UI提供相应API;
• Executer: 执行器;执行任务,负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作;
• Hunter:Spring项目扩展包,负责执行器中的任务抓取,上传注册中心。
4.2 系统架构
4.2.1 Skyworld-Task物理架构部署图
Skyworld-Task:共涉及五个模块:调度中心,执行器,编排中心通过管理平台UI提供编排服务,注册中心,数据持久;
4.2.2 Skyworld-Task逻辑架构图
Skyworld-Task使用SpringBoot体系作为架构选型,基于Quartz及Zookeeper进行二次开发,支持相应的特性功能,下图是Skyworld-Task的整体架构图。
4.3 模块说明
下面对涉及的调度中心、执行器、编排中心、注册中心、数据持久等五个模块分别进行说明:
4.3.1 调度中心
调度中心负责任务调度,负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块; 支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。
调度中心是基于Quartz+自定义线程调度模块+异步Http组件组成,将调度和任务执行完全解耦;逻辑分离,调度器不受任务的编写和发布影响。
调度中心支持集群部署:自实现调度中心的HA,不依赖Quartz的集群方案;实现调度中心的动态扩容/缩容。支持灰度发布升级调度中心,任务可平滑迁移,不受影响。
支持任务HA:调度任务出现异常或调度超时,调度中心可根据用户设置的失败路由策略进行故障转移;每次任务执行时,调度中心都会从注册中心获取最新的执行器实例信息,保证获取调度的执行器实例是可用状态。
支持调度路由:调度路由支持Task级别,解决业务对Task执行资源的特殊需求;用户可根据自身资源或者任务的特定需求来指定对应的路由策略进行调度。
调度模式:目前调度中心支持两种的调度类型:Cron和Fixrate。
调度日志:调度中心会实时记录调度日志,包括Job日志和Task执行日志。调度日志和任务执行过程均可在UI实时查看。
4.3.2 执行模块(执行器)
负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效; 接收“调度中心”的执行请求等。
执行器支持两种类型:
(1) 如果使用 gantry-Task-hunter,支持SpringBoot项目和Spring项目, 引入 gantry-Task-hunter,任务(Task)抓取客户端。合规的HTTP接口(称之为Task)任务会自动被抓去并上传注册中心;
(2) 如果不使用 gantry-Task-hunter,只需提供任务可调用的HTTP接口,此时需要业务手动录入,且自行控制该任务的并发调用控制。
4.3.3 编排中心
编排中心是分布式调度中心支持在线任务模型编排的组件;依托于UI可进行web端任务编排;
Skyworld-Task的编排中心基于DAG保证生成的调度Job中Task之间是有向无环的,支持三种基础任务模型:
(1)串行任务模型:
串行模式示例图
(2)并行任务模型:
并行模式示例图1
并行模式示例图2
(3)分支任务模型:
分支模式示例图
我们可以通过上述基础模型来编排一些复杂的调度模型,例如:
分布式调度框架UI编排界面:
编排界面
编排关系展示界面
4.3.4 注册中心(ZK):
分布式框架采用Zookeeper作为注册中心。
注册中心
(1) 注册服务
调度中心和执行集群都以Zookeeper作为注册中心,所有数据以节点及节点内容的形式注册,通过定时汇报主机状态保持存活在Zookeeper上。
(2) 元数据存储
注册中心不仅仅提供注册服务,并且存储每个执行器的信息(包括执行器实例信息,执行器上传的Task元数据,以及任务运行时的一些临时状态数据)。
(3) 事件发布
基于Zookeeper事件推送机制,进行任务的发布,保证调度器任务抢占的分布均衡。
(4) 负载均衡
保证调度器获取执行Job的个数均衡,避免单一节点压力。
4.3.5 持久化(db):
这里采用MySQL作为数据持久化解决方案。
除了Task动态元数据保存在注册中心之外,其他相关的元数据都存入MySQL,包括但不限于:手动录入的Task,配置的Job信息,编排的Task依赖信息,调度日志,业务人员操作日志,Task执行日志等。
4.4 执行流程
4.4.1 任务的发布流程
(1)用户可以通过UI进行任务创建:可以选择任务类型,设置预警邮箱,设置任务描述。然后为创建的任务进行任务编排。
(2)Job创建完毕并且设置Task编排关系后可进行任务发布,通过UI对相应的Job进行操作(激活,执行一次,停止以及删除操作)。
(3)用户的Task任务可以是通过抓取器抓取的,亦可以使用UI手动创建。
4.4.2 执行流程/状态流转
• 任务执行流程
• 任务执行状态流转
五 Skyworld-Task调度框架主要特性与功能
5.1 特性
• 无侵入
支持Task手动录入和自动抓取(业务需要使用SpringMVC),业务执行逻辑与与调度逻辑无关;
• 可视化
提供webUI界面,操作十分便利;
• 分布式
支持调度分布式部署,以及任务执行器的分布式部署;
• 弹性扩容/缩容
分布式调度框架支持弹性扩容和缩容;
具体业务任务的扩容和缩容也是无缝支持。
• 任务失效转移
任务调度的高可用,对于异常执行器可通过转移策略进行路由一台正常的执行器进行调度。
• 一致性
分布式Job调度与分布式Task调用一致性;
• 任务在线编排
任务支持多种依赖模式(串行,并行,分支),可在线进行任务依赖编排。实时生效。
• 线程池隔离
不同Job由不同线程池调度运行,确保Job调度互相隔离
• 有效性检测
自动检测Task实例节点的有效性;提供执行一次操作,手动检测Job调度的有效性;
• 异步并行
异步调用Task,理论上支持任意时长任务的运行;如果Task之间没有依赖,则并行执行Task;
• 自定义任务参数
支持在线配置调度任务入参,即时生效
• 动态编辑
在线编辑任务时钟参数,实时生效
• 任务运行实时监控
对任务进行全流程监控,并实时展示。
• 邮件预警
提供邮件预警功能,支持预警压制,支持邮件群发。
• 全日志跟踪
实时记录调度日志,Task执行日志,并进行实时展示。
• 跨平台支持
任务调度基于HTTP协议。支持异构应用。
• 任务分片
本版本暂不开放。
5.2 功能
登录系统之后,我们看到首页信息;
本版本主要提供五个功能模块:
• 首页监控;
提供调度信息(调度中心实例,调度器运行Job的信息),接入项目量,以及运行时的Job/Task状态数据监控(可按项目组,Job/Task,时间等维度进行检索)
• 调度器管理
对调度器实例的实时监控,可进行上下调度器,进行任务平滑迁移,版本的灰度发布。
• 任务管理
Task任务管理,支持自动抓取和手动录入;自动抓取的任务不能修改。录入检测Task实例的可达性。
• Job管理
Job任务的创建。
Task依赖的编排。
Job的状态操作(激活,停止,执行一次,删除)。
Job信息修改。
• 调度日志
日志的实时展示,页面显示友好,调度日志和Task执行日志嵌套显示,提升可用性。
5.3 UI
分布式调度框架提供一套完整的webUI,供用户进行操作。
• UI统计监控界面,对调度中心集群状态进行监控统计,对接项目进行统计,业务人员可以通过该页面进行任务全局监控。
• 调度器管理界面。
• ...等,篇幅过多就不一一列举了,分布式调度框架UI 采用前后端分离技术,独立部署。
UI监控界面
调度器管理界面
六 总结
至此对分布式调度框架 Skyworld-Task做了一个简要的介绍,包括产品设计初衷:为什么需要分布式调度框架,设计架构,以及对产品组件特性和功能进行了说明。分布式调度框架 Skyworld-Task解决我们分布式环境的任务调度和任务逻辑耦合的问题,解决我们对分布式环境任务难以管理的困境,提供简单高效的编排调度服务。
Skyworld-Task产品会继续迭代,提供更为完善的服务。之后也会提供相关技术文档和使用文档。敬请期待。
来源:宜信技术学院 作者:毛正卫 李鹏飞
| 留言与评论(共有 0 条评论) |