TaskFlow

TaskFlow
概要

  TaskFlow是为OpenStack(以及其它项目)设计的Python库。TaskFlow可以帮助task便于执行并具有一致性、扩展性和可靠性。它允许通过声明的方式创建轻量级的task对象或者功能,并将其组合到flow中。它包含的engine用来执行、重启、恢复其所管理的flow。使用TaskFlow库的项目,可以获得附加的优势,包括:弹性的状态、自然的声明式构建方法、易测试的(一个task只做一件事)、工作流的即插即用、容错、简化的崩溃恢复机制。
概念中的例子

我们通过下面一个极其简化的例子来描述flow是如何工作的。
开始
task1:调用Nova的API启动一个虚拟机 || 回滚
task2:当task1完成后,调用Cinder的API将块存储挂载到虚拟机上 || 回滚
结束
flow会尝试从“开始”处执行task1,然后执行task2,如果两个task都执行成功,则会从“结束”处退出,整个功能就成功完成了;如果在执行task1过程中有错误发生,即无法成功启动一个虚拟机,则会执行task1的回滚操作,并且退出;如果在执行task2过程中有错误发送,即无法将块存储挂载到虚拟机上,也会执行回滚操作,并且此时不仅执行task2的回滚,也会执行task1的回滚,最后退出。
为什么

  随着OpenStack的发展,代码也在不断的增长,却没有一个标准的和一致的方法在进程异常终止后实现安全的恢复或者回滚。大部分项目甚至都没有尝试让任务具有可重启性或者可恢复性。在现有代码上通过简单地跳过或者进行恢复已经是不可能的了。TaskFlow能够容易地解决这个问题。随着TaskFlow的广泛使用,即使没有部署高可用性配置,OpenStack也会变得可预见的和更可靠的。

服务的停止、更新、重启

  大部分OpenStack子项目是以服务的形式运行的,如果遇到软件升级、硬件故障、维护或者其它各种原因需要停止对应的服务,我们通常使用ststemctl stop <服务名>来停止服务。
  当前,大部分OpenStack子项目不会处理服务被终止后的状态,它们只是简单尝试关闭自己的进程,停止对外的服务,终止正在进行的操作。它们没有提供恢复的机制,当重启启动服务时,它们只是简单的重新开始。TaskFlow会帮助它们跟踪行为、任务和它们的状态,当服务重启后,服务可以进行恢复或者回滚,而不是仅仅简单的重新启动。这种机制能够帮助创建一个容错的体系,避免孤立资源,帮助减少执行清理工作的守护进程,这些守护进程通常周期运行,并且耗费网络和磁盘的性能,即便是有时它们并没有做什么实际的工作。

孤立的资源

  由于大部分OpenStack子项目没有事务的概念,有可能会导致资源处于孤立或者错误状态。孤立的资源难以被检测到;而处于错误状态的资源难以被恢复和处理,所以这两种状态的资源我们都希望尽量避免。TaskFlow提供了一个模型,用来跟踪资源的状态变化,使得所有对资源的操作可以进行回滚操作,确保资源不会处理孤立状态。

度量和历史

  有些OpenStack子项目需要提供度量和历史功能,它们实现此功能的方法是不统一的。通过使用TaskFlow,可以使得多个OpenStack子项目在度量和历史上进行统一。并且TaskFlow也可以解耦度量和历史与实际功能代码之间的关系。开发者可以不必关心TaskFlow的实现机制。

进度和状态跟踪

  在很多OpenStack子项目中都尝试显示正在执行活动的进度。不幸的是,各个子项目实现的方式都不一样。这导致不一致性,并且报告的进度和状态也不准确。TaskFlow通过提供一个插件式的底层机制,可以帮助这些子项目使用统一的方式,简单而容易地添加报告进度和状态的代码。

设计















Atoms

Atom是taskflow的最小单元。类Atom是taskflow中其它类的基类(这是为了避免重复定义功能)。一个atom期望命名输入和输出,以及命名自身的名字和定义版本号。

Tasks

Task是能执行和回滚的最小单元。类Task派生于类Atom。

Retries

Retry是控制一个流flow执行的单元。类Retry派生于类Atom。它可以处理流flow的失败,并且可以使用新的参数重试流flow。

Flows

Flow是一个关联了按照某种次序排列的一个或者多个task的结构。当一个flow执行回滚时,它会执行每个子task的回滚代码。

Patterns

Pattern是将tasks和flows组织的结构。Pattern分为:Linear、Unordered、Graph
Linear:线性的,顾名思义就是一个接着一个执行tasks/flows。前面执行的tasks/fows的输出必须满足后面tasks/flows的输入。
Unordered:没有次序,通常用来执行可以并行执行的tasks/flows。
Graph:根据依赖关系执行tasks/flows。如何多个tasks/flows没有依赖关系,则它们可以并行执行。

Engines

Engine是用来执行flow的。engine使得使用TaskFlow的代码只需关注于workflow的构成,而不用关注执行execution、恢复reverting和重新开始resume。

Jobs

为tasks和flows提供高可用性和可测量性。使得开发者不用担心工作流的分布式和高可用性。

Conductors

为一个运行时单元,提供一个即插即用的概念。

States

tasks/flows的潜在状态迁移。

Notifications

提供关于状态迁移、tasks结果、tasks进度、job委派等等信息的通知。

Reversion

tasks和flows都可以通过执行task对象中相关的回滚代码进行恢复。
例如,下面是一个创建一个虚拟机并且将一个卷挂载的虚拟机的伪代码:
任务1:创建虚拟机 || 回滚1:删除此虚拟机
任务2:创建卷,将卷挂载到虚拟机 || 回滚2:删除此卷
如果在“任务2”中,挂载过程失败,则会执行“回滚1”和“回滚2”,即删除卷和虚拟机,相当于恢复到未执行操作时的状态。

Persistence

TaskFlow可以保存atom(包括task、flow、job)的状态、进度、参数、结果等数据到后端存储。后端存储包括:数据库、内存等等。这些保存的信息用来对atom(包括task、flow、job)进行重新开始、检查和恢复。

Resumption

在一个flow启动之后,结束之前被中断后终止了,它可以从最后的检查点安全的重新执行。这种特性使得服务变得安全和易于从崩溃中恢复。TaskFlow提供了多种保存检查点的存储策略,开发者可以选择合适的存储策略。

Inputs and Outputs

任务的参数称为input;任务的返回值称为output,也称为provide。


参考资料:
  TaskFlow