作业在互联网电商行业中是很常见的技术手段。当当具有成千上万的作业规模,大致分为业务类,归档类,监控类和大数据类。
当当分布式调度原方案
当当原有的作业解决方案是Elastic Job,以下称为Elastic Job 1.X。主要关注以下4个方面:
- 高可用。这里高可用指主从热备。主节点提供服务的同时从节点处于等待状态。一旦主节点失效,其中一个从节点通过选举成为主节点继续提供服务,原来的主节点再次生效后,作为从节点继续等待选举机会。
- 线性扩展。可理解为高可用的高阶功能。既然多节点参与服务提供,若从节点只负责热备,难免造成资源浪费,将主备调整为分片,则可大幅提升处理能力。中心化分布 式服务基本都是提供独立的调度中心和执行节点,调度中心提供主备,执行节点可以弹性的线性扩展。Elastic Job1.X采用无中心化架构,并无调度中心,而是各个执行节点通过Zookeeper选举主节点进行分片、清理等动作,作业调度由执行节点自行触发。Elastic Job 1.X通过分片进行线性扩展,每个执行节点负责处理被分配到的分片项,应用开发者负责分片项和业务逻辑的对应关系。代码示例:
public class MyElasticJob implements SimpleJob {
@Override
public void process(ShardingContext context) {
switch (context.getShardingItem()) {
case 0:
// do something by sharding item 0
break;
case 1:
// do something by sharding item 1
break;
case 2:
// do something by sharding item 2
break;
// case n: ...
}
}
}
- 容错性。主要包括节点失效重分片、失效转移、错过任务重执行以及分布式场景下的脑裂,网络抖动容错等。
- 异构语言。Elastic Job支持Java和Shell,基本能做到异构语言支持。
Elastic Job 的核心组件图如下:
绿色部分是Elastic Job 1.X对开发者提供的API。蓝色部分为内部实现,主要有选举模块、分片模块、调度模块、持久化模块以及分布式协调模块。持久化和协调均基于Zookeeper。
部署架构图如下:
Elastic Job 1.X与应用代码部署在一起,作为lib提供服务。Elastic Job 1.X和运维平台通过注册中心进行交互。
Mesos对云平台解决方案的革新
花了这些篇幅介绍背景,目的是让大家了解当当原有的分布式作业解决方案,接下来将阐述新一代的平台化作业解决方案。
随着时代发展进步,分布式操作系统、容器以及各式各样的容器编排治理方案层出不穷,站在巨人的肩膀上,可以更快速稳定的搭建云平台,基于这样的考虑,我们决定拥抱革新。我们首先将目光投在了Docker上,希望将Elastic Job容器化,然后再选择一个容器治理方案。经过调研,我们转而倾心Mesos,因为我们的目标不是容器化,而是云化,容器是实现云的一种手段,但合理的分布式编排系统更加关键。Docker本身有网络、日志采集等问题需要解决。而Mesos将Docker作为可选容器支持,为了最小化采用新技术带来的风险,我们决定将Docker容器化推迟,先将Elastic Job迁移至Mesos。这也得益于Mesos对Docker的无缝支持,以后加入对Docker的支持非常容易。
下图是Mesos的核心概念:
蓝色是Mesos的基础组件,由Mesos Master、Mesos Agent和运维界面/API组成。Master/Agent的形式在分布式系统中很常见,如Hadoop map-reduce的JobTracker/TaskTacker。Mesos Master节点通过Zookeeper实现高可用,用于分配资源至注册在Mesos的 Framework,Mesos Agent用于收集宿主机资源,如可用CPU、内存、甚至GPU等,并负责执行Mesos Framework分发的任务。Mesos Master与Slave间使用内部API交互,通过远程执行部署在Mesos Agent的程序无需Mesos Agent所在服务器提供免登录账号。
紫色是Mesos Framework的组成部分。Mesos只有基础组件并不能独立使用,需要注册Framework接收Mesos Master分配的资源并决定如何执行,目前常见的Marathon和Chronos都是Mesos Framework。Framework的两个重要组成是Scheduler和Executor。Scheduler和Mesos Master通过Scheduler API交互,负责将分配的资源生成任务并分发。Executor通过Executor API与Mesos Agent交互,负责执行分配的任务并回告状态。
红色是Scheduler中两个最重要的回调方法,resourceOffers和statusUpdate。
resourceOffers用于将资源转化为任务并调用Executor执行。资源分配算法,任务业务逻辑都应在此方法中实现。
statusUpdate用于处理Executor回传的状态。可通过Executor的状态传递和Scheduler的statusUpdate实现失效转等的分布式协调功能。
Executor分为两种。
Marathon和Chronos都使用Command Executor,这也是Mesos提供的内置的Executor,可以直接执行命令行脚本,也提供了基本的状态回传功能,对于普通应用使用Command Executor是不错的选择。
自定义Executor可提供更多灵活性。下面举几个例子,但不限于仅实现这些功能。
- 日志重定向。Command Executor的日志会输出到Mesos提供的沙箱中,通过自定义Executor可将日志重定向到其他文件,或对接其他日志收集工具。
- 多任务复用。Command Executor与任务是一对一的关系。有些初始化资源非常耗时的场景,可以复用Executor,多线程并发处理多任务。
- 执行进度报告。Command Executor仅回告状态变化,如需更加细化进度回告功能,需定制化处理。
- 心跳检测。可以通过Executor定时传递消息做心跳检测。
简单的介绍了Mesos,是该讨论下Mesos能带来什么好处的时候了。Mesos可作为部署平台和运行平台使用。
作为部署平台,Mesos可以做到应用分发自动化。将应用上传到网络地址(或Docker仓库),Mesos能够自动将应用分发至需要执行相关任务的Mesos Agent,省去人工部署成本。由于应用自动分发,那么CMDB将大大简化,只需要管理Zookeeper服务器即可,Mesos Master、Mesos Agent以及其他部署在Mesos内部的应用均可用Mesos界面统一管理。美中不足是Mesos目前缺乏管理数据类服务器的成功案例,数据库等部署在Mesos之外的应用仍需独立的CMDB管理。
作为运行平台,Mesos可以将资源收集至统一资源池,做到硬件资源与应用一体化,按需分配资源,自动资源回收,减少资源闲置和浪费。
应用分发、资源分配和安全管理,即可形成云平台的雏形,由于当当仅搭建私有云,安全管理暂时不是重点。
现在再分析Elastic Job 1.X的解决方案,应用分发和资源分配部分是缺失的。
基于Mesos开发作业云Elastic Job Cloud
决定基于Mesos搭建作业云,我们开始调研实现方案。首先想到自然是拥抱开源,不重复发明轮子。方案A是使用Marathon作为调度框架。
方案A的优点是可以实现应用分发和资源分配,并且是高可用的解决方案。
但缺点同样明显:
- 资源分配静态化,作业无论执行与否均需预分配资源;
- Executor无法复用,对于Elastic Job这种对内部状态报告有要求的框架,需要在框架中通过第三方存储汇报状态;
- 跨机房等定制化功能较困难;
- 使用繁琐,需要使用Mesos、Marathon和Elastic Job 3个管理界面。
另一种类似的方案是使用Chronos,可以做到动态资源分配,但缺点是:
- 不支持CRON表达式,对于原crontab或Quartz的应用迁移不友好;
- 不适合低延迟作业,每次启动初始化资源会消耗时间,导致作业延迟,反复初始化也容易造成资源浪费;
- 定制功能仍然困难。
说到这里需要抛出常驻作业和瞬时作业概念了。
常驻作业是作业一旦启动,无论运行与否均占用系统资源;瞬时作业是在作业启动时占用资源,运行完成后释放资源。
常驻作业适合初始化时间长、触发间隔短、实时性要求高的作业,要求资源配备充足。
瞬时作业适合初始化时间短、触发间隔长、允许延迟的作业,一般用于资源不太充分,或作业要求的资源多,适合资源错峰使用的场景。
由于上述缺点,我们最终选择方案B。
我们决定自行开发Mesos Framework,项目的名称叫做Elastic Job Cloud。优点:
- 包含方案A的全部优点;
- 资源分配静态与动态相结合,常驻与瞬时作业分离处理;
- Elastic Job 1.X的核心理念仍可沿用,包括分片,以及之前未提及的功能,如多种作业类型,事件统计等;
- 易于定制化需求开发。
Elastic Job Cloud核心组件图如下:
绿色的API部分变化不大;红色的内部实现部分,无论是模块本身,还是模块的内部实现均有大幅度调整。
选举模块由执行节点主节点选举变更为主Mesos Framework选举,仍然依赖Zookeeper。
Sharding模块功能未变,但从执行节点主节点分片调整为Mesos Framework集中分片。Elastic Job 1.X的分片以IP为依据,Elastic Job Cloud更改为以运行任务实例为依据。
调度引擎从去中心化执行节点调度转变为Mesos Framework的中心节点调度。
通过调度作业向任务队列中写入待执行作业。
日志输出方式变更为事件发布,可自行监听发布的事件,收集Elastic Job Cloud的运行状态,默认提供日志和数据库(推荐)两种事件收集方式。
通过Executor和Scheduler API配合进行分布式协调,替换通过Zookeeper协调的方案,有效的减少了与Zookeeper的连接数。
Elastic Job Cloud作为Mesos Framework独立部署,将作业信息存入Zookeeper。
虽然Elastic Job Cloud可以提供中心化云解决方案,但Elastic Job 1.X作为无中心化解决方案,仍适用于中小规模的分布式作业调度场景。我们并未放弃Elastic Job 1.X,将其更名为Elastic Job Lite。Elastic Job Lite和Elastic Job Cloud共同组成Elastic Job,核心组件全景图如下:
Elastic Job Lite和Elastic Job Cloud使用统一的Elastic Job API,开发者在开发时无需关心最终的部署方式。部署在Lite或Cloud环境无需修改业务作业代码,秩序调整配置和启动方式即可。Lite和Cloud的差别仅在于云平台需要的应用分发和资源调度一体化。
目前Elastic Job Cloud已开发完成并在公司内部试用。日前对接监控系统的万余作业,全天运行峰值百万左右。
Elastic Job Cloud的roadmap是:
- 公司内部大规模推广使用;
- Docker支持;
- 任务优先级、依赖以及编排的支持;
- 跨机房部署、物理机隔离等功能开发。
回馈开源社区
目前Elastic Job已全部开源。项目地址,欢迎感兴趣的人踊跃尝试。
最后我分享下我们这4个月以来的里程碑。
本文由当当网架构专家张亮在CNUTCon北京2016 全球容器技术大会上的演讲整理而成。