批量计算概念介绍

引题:工作负载分类

工作负载的分类方法和标准多种多样,其中 Google 提出的一种简单的分类标准广受认可,即将工作负载分为服务型和批处理型。

  • 服务型 service
    • 长时间运行,理论上不会停止,对服务质量敏感,主要是线上业务
    • 例如 web 服务,e-mail 服务等
  • 批处理型 batch
    • 运行时间从几秒到几天不等,对短时性能波动相对不敏感,主要是离线业务
    • 例如日志分析等

公有云上的批量计算

最初,公有云的工作负载以服务型负载为主,各大厂商也进行了诸多针对性优化。随着云计算的快速发展,越来越多的、不同行业的用户开始使用公有云,批处理型负载显著增加。针对批处理型负载的需求,我们也通过新的产品形式来满足用户。

  • 专注业务,支持大规模自动化调度与执行,为用户屏蔽资源细节。
  • 调度逻辑,支持 DAG 和优先级调度,满足用户复杂的业务处理逻辑。
  • 成本优化,支持资源的动态伸缩,按需分配资源,避免资源浪费,节省成本。

腾讯云 Batch 模型

  • 执行单元
    • Job,作业,一组关联 Task 的集合
    • Task,任务,指明执行逻辑和资源需求
    • TaskInstance,任务实例,原子执行单元,一个 Task 可并行执行多份
  • DAG依赖
    • 通过图拓扑表示 DAG 依赖,Job 是 DAG 图,Task 是点,依赖 Dependence 是边
    • Task 是依赖关系的维护单元,不使用 TaskInstance 作为依赖关系的维护单元是为了防止依赖关系爆炸

批量计算完整流程

上一小节是腾讯云 Batch 自身的逻辑模型。本节我们将视角提升到整个处理流程,涵盖调度、计算、存储等方面。流程示意图如下图所示。

  • 主要步骤
    1. 用户上传应用程序和输入文件到对象存储COS上
    2. 用户提交 Batch 作业
    3. Batch 创建 CVM 实例
    4. CVM 实例中启动 Batch agent,从 COS 下载应用程序和输入文件,执行任务实例
    5. Batch agent 上传输出文件到 COS
    6. 用户监控 Batch 作业的结果
    7. 用户在 Batch 作业完成后,从 COS 下载获得输出文件
  • 腾讯云闭环
    • 整个流程在腾讯云上实现调度、计算、存储闭环
    • Batch 提供调度分发能力
    • CVM 提供计算能力
    • COS 提供持久化存储能力

竞品调研关键问题

在进行产品规划、系统设计的过程中,我们对公有云批量计算产品进行了较为充分的调研,涵盖 AWS, Aliyun, Azure, Google Cloud等友商(其中 Google Cloud Batch 是 Google Dataflow 产品的一部分,专注数据处理,与其他竞品差别较大,不作为主要对比系)。我们从中汲取了大量养分,同时也发现对于一些关键问题和产品规划,不同厂商采用了不同的策略。对此,我们尝试分析背后的产品逻辑和各自优劣,结合目标用户的需求,选择确定了腾讯云批量计算的产品路线。

虚拟机与任务实例的耦合关系

  • AWS
    • 产品策略:作业与 VM 生命周期解耦。一个 VM 可以运行多个作业,作业分配到 VM 需要装箱。
    • 简评:AWS Batch 作业通过容器的方式执行,看起来可以快速启动,但是容器仍然需要运行在 VM 之中,VM 的规格和启停时机难以把握。在试用过程中,我们发现 AWS Batch 容易出现资源浪费和资源“假死锁”问题。客观来说,容器与 VM 2层概念增加了产品逻辑复杂度,而 AWS Batch 并没有完满的处理好这方面的产品逻辑。
    • 问题1 资源浪费
      • 在一个MaxvCPU(AWS Batch 产品概念,大意为计算环境可使用的 CPU 上限)为16C的环境中,用户先提交一个16C的作业A, AWS Batch 会自动创建一个16C的 EC2 实例执行作业A。然后用户再提交一个8C的作业B,在作业A完成之后,AWS Batch 会复用16C的 EC2 实例执行作业B。AWS Batch的收费策略是根据 EC2 实例收费,这样存在一个问题,在执行作业B的时候,Batch 用16C的 EC2 执行8C的作业,造成了资源浪费。实际上,用户提交作业的规格和吞吐量发生变化是较为常见的事情,这样的 case 比较容易出现。
      • 此外,作业执行完成后,EC2 不会立即销毁,通常会保留数十分钟后才会自动释放,对于不持续提交作业的用户,也会造成明显的资源浪费。

- 问题2 资源“假死锁”
    - 在一个MaxvCPU为16C的环境中,用户先提交一个8C的作业A,AWS Batch 会自动创建一个8C的 EC2 实例来执行作业 A。然后提交一个16C的作业B。本来预期 AWS Batch 会立即销毁现有的 EC2 实例,然后创建一个新的16C EC2 实例来运行作业B。但是,实际情况要略差于预期,在作业B提交近一小时之后,AWS Batch才创建了16C的 EC2 实例,完成计算环境的调整,以至于用户一度认为 AWS Batch 出现了死锁 bug。虽然最终没有造成死锁,但是 AWS Batch 的调整延迟过大,影响用户体验。

  • Aliyun
    • 产品策略: Aliyun Batch 分为2种计算环境类型,AutoCluster 自动集群模式和 Cluster 固定集群模式。对于 AutoCluster 模式,任务实例与 VM 生命周期一致;对于 Cluster 模式,虽然任务实例与 VM 生命周期不一致,但是目前仍然采用1对1模式,即 VM 同时只运行一个任务实例。
    • 简评:Aliyun Batch,特别是 AutoCluster 模式,产品逻辑简单直接。
  • Azure
    • 产品策略: 任务与 VM 生命周期解耦。一个 VM 可以运行多个任务。与 AWS Batch 不同,任务分配到 VM 不进行装箱,而是通过参数设置,即一个 VM 可以同时运行 n 个任务,n 可设置。。
    • 简评:与 AWS Batch 类似,可能出现浪费资源的问题。不进行装箱,直接为 VM 分配 n 个任务的策略,对于异构化的任务,存在资源评估不准确的问题。
  • 用户反馈
    • 用户关心业务本身,对耦合关系无明显偏好,希望产品逻辑保持简洁直观,避免资源浪费。
  • 腾讯云做法
    • CVM 和 任务实例生命周期耦合,一一对应,执行任务实例前夕创建 CVM 实例,执行完成后立即销毁 CVM 实例。保证按需分配和使用资源,节省成本。
    • 同时,充分利用 CVM 快速创建优势,快速响应 Batch 业务。

执行单元的层级关系

  • AWS
    • 产品策略:执行单元为 Job,是原子执行单元,相当于腾讯云的 TaskInstance。
    • 简评:保证接口原子性。虽然可以通过指定前序 Job 来表示 Job 间的依赖关系,但是需要用户记录和维护前序 Job 的唯一 ID,并在提交后序 Job 时指定前序 Job 的唯一 ID,相当于用户需要参与维护DAG 关系。同时,AWS Batch 目前无法提供完成的 DAG 视图。
  • Aliyun
    • 产品策略:Job、Task、Instance三层单元
      • 简评:可以在 Job 内部实现 DAG 关系。Aliyun Batch 和 ECS 是两款产品,但是二者的 Instance 和 InstanceId 容易混淆。Aliyun Batch 中存在 InstanceId 的概念,却并非 ECS InstanceId,而是类似 Instance 在 Task 内部索引的概念。
  • Azure
    • 产品策略:具有 Job 和 Task 两层单元,Job 其实是类似队列或者任务集合的静态概念,Task 是其执行单元。
    • 简评:Azure Batch 中的 Task 类似于 AWS Batch 中的 Job,二者优缺点相似。
  • 用户反馈
    • 希望 Batch 产品可以优雅地处理 DAG 关系,同时对用户简单。
  • 腾讯云做法
    • 借鉴工作流系统 airflow 的命名方式,采用 Job、Task、TaskInstance 三层执行单元。
    • TaskInstance 与 CVM Instance 概念区分。虽然我们目前采用 TaskInstance 和 CVM Instance 生命周期一致的策略,但是二者本身不同,不要混淆。

CVM 用户是否可见

  • AWS
    • Batch 创建的虚拟机,在其控制台可见
  • Aliyun
    • Batch 创建的虚拟机,在其控制台不可见,不可直接登录。虽然 Aliyun Batch 提供了内网连通的拓展功能,但是产品体验有待提高。
  • Azure
    • Batch 创建的虚拟机,在其控制台可见
  • 用户反馈
    • 多方用户提到友商 Batch 创建虚拟机控制台不可见、无法登录的痛点。当出现问题时较难定位。
  • 腾讯云做法
    • 保证“搭积木式”的产品观
    • Batch 和用户使用相同的方式使用基础产品(例如 CVM),保证基础产品逻辑一致

系统设计

TaskInstance 状态机

腾讯云 Batch 包括 Job、Task、TaskInstance 三层执行单元,TaskInstance 系原子执行单元,这里介绍其状态机。Job、Task 的状态依赖其所含 TaskInstance 的状态,不做展开。

  • SUBMITTED
    • 已经接收到 Job 并解析拆分。
    • 如果存在依赖项,则任务实例进入 PENDING 状态,否则进入 RUNNABLE 状态。
  • PENDING
    • 驻留在队列中,因为等待其他依赖任务,而无法运行
    • 在满足依赖关系后,任务实例将进入 RUNNABLE 状态。
  • RUNNABLE
    • 驻留在队列中且没有任何未完成依赖项,因为没有资源或者资源配额不足而暂时无法运行
    • 当资源足够时,任务实例会被调度运行。
  • STARTING
    • 任务实例完成调度开始执行和下发,任务实例尚未启动执行
  • RUNNING
    • 任务实例在计算环境中运行
    • 当应用程序退出时,进程退出代码将确定任务实例是成功还是失败。退出代码 0 表示成功,非零退出代码表示失败。
  • SUCCEEDED
    • 任务实例成功完成,返回码为 0
  • FAILED
    • 在执行所有可用尝试后,任务实例失败。

系统架构与设计细节

定位为工作流 workflow 系统,适用于 Batch 场景,命名为 Wonderflow。

  • Wonderflow API
    1. 生成唯一 JobId,并将 Job 基本信息提交到数据库中
    2. 将 Job 完整信息发送至 MQ 中
    3. 向调用方返回 JobId
  • 依赖关系
    • Job 拆分时,根据有无依赖,将 TaskInstance 的状态设置为 PENDING 或者 RUNNABLE
    • TaskInstance 完成后,会变更关联对象的状态,可能包括 Task、Job、后续 Task、后续 TaskInstance 的状态。
  • 调度策略
    • 以 owner 为粒度进行集中调度,查询同一 owner、状态为 RUNNABLE 的 TaskInstance,按照优先级排序,逐个遍历
      1. 如果 TaskInstance 有足够资源配额,则下发执行,将 TaskInstance 信息发送至pre-executor MQ
      2. 如果 TaskInstance 无足够资源配额,则continue
    • owner 之间并行调度;同一 owner 串行调度,避免无意义加锁。
    • TaskInstance 存储使用数据库,不使用优先级队列,避免“队列头阻塞”或者优先级变化。
  • Wonderflow 内部回滚
    • pre-executor 和 post-executor 相对复杂,需要内部回滚
    • 例如 pre-executor 如果执行失败,进行回滚,销毁已经创建的 CVM 实例
  • Wonderflow 与 CVM API 交互
    • 支持两种模式,调用内部 CVM API 和 SDK
    • 默认采用 CVM API 模式,应用在腾讯公有云场景下
    • 可选通过 SDK 模式,与 CVM 用户行为完全一致,意味着用户可以在自己的 CVM 集群中搭建 Wonderflow 系统并直接使用。
  • 与CVM实例的交互
    • 镜像只需安装 cloudinit,而无须提前嵌入 Batch agent,即可运行批量计算作业
    • cloudinit 是业界认可的标准初始化工具,镜像制作标准规范、简易
    • 腾讯云计划近期更新主流公有镜像,使之支持 cloudinit

设计原则小结

  • “搭积木”
    • 批量计算保证基础产品的原生能力,不进行封装或阉割。批量计算和用户使用基础产品的方式一致,保证产品表现一致
  • 多调度器并发架构
    • 多调度器并发调度,用户(owner)级别并发,类似于 Google Omega 的无锁乐观并发调度架构, 可提升调度系统的吞吐率。用户(owner)内部串行,保证按照优先级调度下发,同时避免无意义加锁。
    • 在产品调度策略上,目前批量计算对所有用户采用对等公平策略。如果特定场景(比如私有云环境)需要采用相对公平策略,不同用户具有不同的权重值,则需要增加一个调度组件和一层调度策略,决定优先为哪个/哪些用户进行调度。
  • 轻量 API
    • API 逻辑轻量,保持快速响应
    • 复杂逻辑交由异步消费者完成
  • 消费者处理逻辑简洁明确
    • TaskInstance 状态机相对复杂,但是每类消费者只做一类事,相当于解耦了状态机。
    • 例如,Splitter 负责拆分Job,根据 TaskInstance 有无依赖将状态置为 PENDING 或者 RUNNABLE;Scheduler 只负责调度下发状态为 RUNNABLE 的 TaskInstance,不会考虑依赖关系;post-executor 在销毁 CVM 实例之后,负责变更 TaskInstance 状态和关联对象状态,会将已经无依赖的后续 TaskInstance 状态从 PENDING 变更为 RUNNABLE。

核心功能与产品优势

  • 自动托管
    • 自动调度、下发、执行海量作业,为用户屏蔽资源细节,专注业务本身。
  • DAG 依赖
    • 通过 DAG 拓扑形式,描述任务间依赖关系,根据依赖关系保证任务的先后执行顺序。通过简单形式满足用户复杂处理逻辑的业务需求。
  • 优先级调度
    • 对于无依赖任务实例,基于优先级进行先后调度。
  • 计算资源动态伸缩
    • 资源与任务实例生命周期一致,根据业务需求动态扩展和释放计算资源,按需分配资源,避免浪费,节省成本。
  • 天然集成
    • Batch 与腾讯云基础产品天然集成,涵盖计算(CVM)、网络(VPC)、存储(COS/CFS)、安全(安全组)等多个方面,用户业务可在腾讯云上轻松闭环。
    • 复用基础产品优势,例如腾讯云 CVM 快速创建。
  • 调试 Debug 模式
    • TaskInstance 失败后,CVM 实例不销毁,保留现场
    • 批量计算创建的 CVM 实例,在 CVM 控制台可见、可登陆,便于用户观察应用运行状态。

批量计算作为一款新产品,可能还存在一些不足,也欢迎大家多多试用 & 反馈问题。

参考

[1] Schwarzkopf, Malte, et al. "Omega: flexible, scalable schedulers for large compute clusters." Proceedings of the 8th ACM European Conference on Computer Systems. ACM, 2013.
[2] Verma, Abhishek, et al. "Large-scale cluster management at Google with Borg." Proceedings of the Tenth European Conference on Computer Systems. ACM, 2015.
[3] Konwinski A D. Multi-agent cluster scheduling for scalability and flexibility[M]. University of California, Berkeley, 2012.
[4] AWS Batch. https://aws.amazon.com/cn/batch/
[5] Azure Batch. https://azure.microsoft.com/en-us/services/batch/
[6] Aliyun BatchCompute. https://www.aliyun.com/product/batchcompute
[7] Google Dataflow. https://cloud.google.com/dataflow/

文章来源于腾讯云开发者社区,点击查看原文