创建任务依赖关系,以运行依赖于其他任务的任务

可以定义任务依赖关系,以便仅在完成父任务后,才运行一个或一组任务。 任务依赖关系可发挥作用的部分方案包括:

  • 云中的 MapReduce 样式工作负荷。
  • 数据处理任务可以表示为有向无环图 (DAG) 的作业。
  • 渲染前和渲染后过程,其中只有在完成每个任务后,其后续任务才能开始。
  • 下游任务依赖于上游任务输出的任何其他作业。

使用批处理任务依赖关系,可以创建在完成一个或多个父任务后在计算节点上按计划执行的任务。 例如,可以创建一个作业,使用单独的并行任务渲染 3D 影片的每个帧。 最后一个任务为“合并任务”,仅在所有帧已成功渲染后,才将渲染的帧合并为完整影片。

默认情况下,依赖任务计划为仅在成功完成父任务后执行。 可以指定一个依赖关系操作来重写默认行为,并在父任务失败时运行任务。 有关详细信息,请参阅依赖关系操作部分。

用户可以创建依赖于一对一或一对多关系中其他任务的任务。 甚至可以创建一个范围依赖关系,使其中一项任务依赖于特定任务 ID 范围内一组任务的完成。 你可以组合这三种基本方案,以创建多对多关系。

Batch .NET 的任务依赖关系

本文讨论如何使用 Batch .NET 库配置任务依赖关系。 本文首先说明如何为作业启用任务依赖关系,然后演示如何为任务配置依赖关系。 本文还将介绍如何指定一个依赖关系操作,以便在父任务失败时运行依赖任务。 最后介绍 Batch 支持的依赖关系方案

启用任务依赖关系

若要在批处理应用程序中使用任务依赖关系,必须先将作业配置为使用任务依赖关系。 在 Batch .NET 中,为 CloudJob 启用任务依赖关系的方法是将其 UsesTaskDependencies 属性设置为 true

CloudJob unboundJob = batchClient.JobOperations.CreateJob( "job001",
    new PoolInformation { PoolId = "pool001" });

// IMPORTANT: This is REQUIRED for using task dependencies.
unboundJob.UsesTaskDependencies = true;

在以上代码片段中,“batchClient”是 BatchClient 类的一个实例。

创建依赖任务

若要创建一个依赖于一个或多个父任务的完成的任务,可以指定该任务必须“依赖于”其他任务。 在 Batch .NET 中,为 CloudTask.DependsOn 属性配置 TaskDependencies 类的一个实例:

// Task 'Flowers' depends on completion of both 'Rain' and 'Sun'
// before it is run.
new CloudTask("Flowers", "cmd.exe /c echo Flowers")
{
    DependsOn = TaskDependencies.OnIds("Rain", "Sun")
},

此代码片段创建任务 ID 为“Flowers”的依赖任务。 “Flowers”任务依赖于“Rain”和“Sun”任务。 “Flowers”任务将计划为仅在“Rain”和“Sun”任务已成功完成后才在计算节点上运行。

Note

当任务处于已完成状态并且其退出代码0 时,该任务视为已成功完成。 在 Batch .NET 中,这意味着 CloudTask.State 属性值为 Completed,CloudTask 的 TaskExecutionInformation.ExitCode 属性值为 0

依赖关系方案

可以在 Azure Batch 中使用三种基本任务依赖关系方案:一对一、一对多和任务 ID 范围依赖关系。 可以组合这些方案以提供第四种方案:多对多。

方案        示例
一对一 taskB 取决于 taskA

taskA 成功完成后,taskB 才会按计划执行

关系图:一对一任务依赖关系
一对多 taskC 同时取决于 taskAtaskB

taskAtaskB 成功完成后,taskC 才会按计划执行

关系图:一对多任务依赖关系
任务 ID 范围 taskD 取决于一系列任务

ID 为 110 的任务成功完成后,taskD 才会按计划执行

关系图:任务 ID 范围依赖关系
Tip

可以创建多对多关系,例如,在此关系中任务 C、D、E 和 F 都依赖于任务 A 和 B。这很有用,例如,在下游任务依赖于多个上游任务的输出的并行化预处理方案中,即可以这样操作。

在本部分的示例中,仅在父任务成功完成时才运行依赖任务。 此行为是依赖任务的默认行为。 可以通过指定一个依赖关系操作来重写默认行为,在父任务失败后运行依赖任务。 有关详细信息,请参阅依赖关系操作部分。

一对一

在一对一关系中,任务依赖于一个父任务的成功完成。 若要创建该依赖关系,请在填充 CloudTaskDependsOn 属性时,为 TaskDependencies.OnId 静态方法提供单个任务 ID。

// Task 'taskA' doesn't depend on any other tasks
new CloudTask("taskA", "cmd.exe /c echo taskA"),

// Task 'taskB' depends on completion of task 'taskA'
new CloudTask("taskB", "cmd.exe /c echo taskB")
{
    DependsOn = TaskDependencies.OnId("taskA")
},

一对多

在一对多关系中,任务依赖于多个父任务的完成。 若要创建该依赖关系,请在填充 CloudTaskDependsOn 属性时,为 TaskDependencies.OnIds 静态方法提供任务 ID 的集合。

// 'Rain' and 'Sun' don't depend on any other tasks
new CloudTask("Rain", "cmd.exe /c echo Rain"),
new CloudTask("Sun", "cmd.exe /c echo Sun"),

// Task 'Flowers' depends on completion of both 'Rain' and 'Sun'
// before it is run.
new CloudTask("Flowers", "cmd.exe /c echo Flowers")
{
    DependsOn = TaskDependencies.OnIds("Rain", "Sun")
},

任务 ID 范围

在依赖于一系列父任务的关系中,任务依赖于其 ID 位于某个范围内的任务的完成。 若要创建该依赖关系,请在填充 CloudTaskDependsOn 属性时,为 TaskDependencies.OnIdRange 静态方法提供该范围内的第一个和最后一个任务 ID。

Important

将任务 ID 范围用于依赖关系时,范围内的任务 ID 必须采用整数值的字符串表示形式。

范围内的每个任务必须通过成功完成或者已完成但出现了映射到设置为 Satisfy 的某个依赖关系操作的失败,来满足该依赖关系。 有关详细信息,请参阅依赖关系操作部分。

// Tasks 1, 2, and 3 don't depend on any other tasks. Because
// we will be using them for a task range dependency, we must
// specify string representations of integers as their ids.
new CloudTask("1", "cmd.exe /c echo 1"),
new CloudTask("2", "cmd.exe /c echo 2"),
new CloudTask("3", "cmd.exe /c echo 3"),

// Task 4 depends on a range of tasks, 1 through 3
new CloudTask("4", "cmd.exe /c echo 4")
{
    // To use a range of tasks, their ids must be integer values.
    // Note that we pass integers as parameters to TaskIdRange,
    // but their ids (above) are string representations of the ids.
    DependsOn = TaskDependencies.OnIdRange(1, 3)
},

依赖关系操作

默认情况下,只有在父任务成功完成后,才能运行某个依赖任务或任务集。 在某些情况下,你可能希望即使父任务失败,也能运行依赖任务。 可以通过指定依赖关系操作来重写默认行为。 依赖关系操作根据父任务的成功或失败状态指定某个依赖任务是否符合运行的条件。

例如,假设某个依赖任务正在等待完成上游任务后提供的数据。 如果上游任务失败,依赖任务仍可使用旧数据运行。 在这种情况下,依赖关系操作可以指定即使父任务失败,依赖任务也符合运行的条件。

依赖关系操作基于父任务的退出条件。 可为以下任一退出条件指定依赖关系操作;对于 .NET,请参阅 ExitConditions 类了解详细信息:

  • 预处理错误发生时。
  • 文件上传错误发生时。 如果任务退出并返回通过 exitCodesexitCodeRanges 指定的退出代码,然后遇到文件上传错误,则优先执行退出代码指定的操作。
  • 任务退出并返回 ExitCodes 属性定义的退出代码时。
  • 任务退出并返回处于 ExitCodeRanges 属性指定的范围内的退出代码时。
  • 默认情况下,如果任务退出时返回 ExitCodesExitCodeRanges 未定义的退出代码,或者如果任务退出时返回预处理错误并且 PreProcessingError 属性未设置,或者如果任务失败时返回文件上传错误并且 FileUploadError 属性未设置。

若要在 .NET 中指定依赖关系操作,请为退出条件设置 ExitOptions.DependencyAction 属性。 DependencyAction 属性采用以下两个值之一:

  • DependencyAction 属性设置为 Satisfy 表示在父任务退出并返回指定的错误时,依赖任务符合运行的条件。
  • DependencyAction 属性设置为 Block 表示依赖任务不符合运行的条件。

对于退出代码 0,DependencyAction 属性的默认设置为 Satisfy;对于其他退出条件,其默认设置为 Block

以下代码片段设置父任务的 DependencyAction 属性。 如果父任务退出并返回预处理错误或指定的错误代码,则依赖任务将被阻止。 如果父任务退出并返回其他任何非零错误,依赖任务将符合运行的条件。

// Task A is the parent task.
new CloudTask("A", "cmd.exe /c echo A")
{
    // Specify exit conditions for task A and their dependency actions.
    ExitConditions = new ExitConditions()
    {
        // If task A exits with a pre-processing error, block any downstream tasks (in this example, task B).
        PreProcessingError = new ExitOptions()
        {
            DependencyAction = DependencyAction.Block
        },
        // If task A exits with the specified error codes, block any downstream tasks (in this example, task B).
        ExitCodes = new List<ExitCodeMapping>()
        {
            new ExitCodeMapping(10, new ExitOptions() { DependencyAction = DependencyAction.Block }),
            new ExitCodeMapping(20, new ExitOptions() { DependencyAction = DependencyAction.Block })
        },
        // If task A succeeds or fails with any other error, any downstream tasks become eligible to run 
        // (in this example, task B).
        Default = new ExitOptions()
        {
            DependencyAction = DependencyAction.Satisfy
        }
    }
},
// Task B depends on task A. Whether it becomes eligible to run depends on how task A exits.
new CloudTask("B", "cmd.exe /c echo B")
{
    DependsOn = TaskDependencies.OnId("A")
},

代码示例

TaskDependencies 示例项目是 GitHub 上的 Azure Batch 代码示例之一。 此 Visual Studio 解决方案演示了:

  • 如何在作业中启用任务依赖关系
  • 如何创建依赖于其他任务的任务
  • 如何在计算节点池中执行这些任务。

后续步骤

应用程序部署

使用 Batch 的应用程序包功能,可以轻松地部署任务在计算节点上执行的应用程序并对其进行版本控制。

安装应用程序和暂存数据

有关准备节点以运行任务的方法概述,请参阅 Azure Batch 论坛中的 Installing applications and staging data on Batch compute nodes(在批处理计算节点上安装应用程序和暂存数据)。 此帖子由某个 Azure Batch 团队成员编写,是一篇很好的入门教程,介绍如何使用不同的方法将应用程序、任务输入数据和其他文件复制到计算节点。