使用适用于 .NET 的 Batch 文件约定库将作业和任务数据保存到 Azure 存储

在 Azure Batch 中运行的任务可能在其运行时产生输出数据。 通常需要存储任务输出数据,以便作业中的其他任务和/或执行该作业的客户端应用程序进行检索。 任务可向 Batch 计算节点的文件系统写入输出数据,但当重置节点映像或节点离开池时,节点上的所有数据都会丢失。 任务可能还具有文件保留期,超过此保留期后,系统将删除该任务创建的文件。 出于这些原因,请务必将以后需要的任务输出保留到数据存储,如 Azure 存储

有关 Batch 中的存储帐户选项,请参阅 Batch 帐户和 Azure 存储帐户

可以使用适用于 .NET 的文件约定库持久保存 Azure Batch 中的任务数据。 文件约定库简化了在 Azure 存储中存储和检索任务输出数据的过程。 你可以在任务代码和客户端代码中使用文件约定库。 在任务模式下,使用库来保存文件。 在客户端模式下,使用库来列出和检索文件。 任务代码还可以使用库来检索上游任务的输出(例如,在任务依赖关系方案中这样使用)。

若要使用文件约定库检索输出文件,请找到作业或任务的文件。 不需要知道文件的名称或位置。 相反,你可以按 ID 和用途列出文件。 例如,列出给定任务的所有中间文件。 或者,获取给定作业的预览文件。

从 2017-05-01 版开始,Batch 服务 API 支持将在池(使用虚拟机 (VM) 配置创建)中运行的任务和作业管理器任务的输出数据保存到 Azure 存储。 你可以在创建任务的代码中保存输出。 此方法是文件约定库的替代方法。 可以修改 Batch 客户端应用程序来保存输出,而无需更新任务运行的应用程序。 有关详细信息,请参阅使用 Batch 服务 API 将任务数据保存到 Azure 存储

库用例

Azure Batch 提供多种方法来保存任务输出。 在需要执行以下操作时使用文件约定库:

  • 修改任务正在运行的应用程序的代码以保存文件。
  • 在任务仍运行的情况下,将数据流式传输到 Azure 存储。
  • 保存池中的数据。
  • 在客户端应用程序或其他任务中按 ID 或用途查找并下载任务输出文件。
  • 在 Azure 门户中查看任务输出

对于其他方案,可能需要考虑其他方法。 有关其他选项的详细信息,请参阅将作业和任务输出保存到 Azure 存储

什么是 Batch 文件约定标准?

Batch 文件约定标准为输出文件要写入到的目标容器和 Blob 路径提供命名方案。 你可以在 Azure 门户中自动查看保存在 Azure 存储中且符合该标准的文件。

适用于 .NET 的文件约定库会自动根据该标准为存储容器和任务输出文件命名。 该库还提供用于查询 Azure 存储中的输出文件的方法。 你可以按作业 ID、任务 ID 或用途进行查询。

如果使用 .NET 之外的语言进行开发,则可在应用程序中自行实现文件约定标准。 有关详细信息,请参阅实现 Batch 文件约定标准

若要使用文件约定库将输出数据保存到 Azure 存储,请先将 Azure 存储帐户关联到 Batch 帐户。

  1. 登录 Azure 门户
  2. 在搜索栏中搜索并选择“Batch”。
  3. 选择要与 Azure 存储关联的 Batch 帐户。
  4. 在 Batch 帐户页面的“设置”下,选择“存储帐户”。
  5. 如果尚未将 Azure 存储帐户与 Batch 帐户关联,请选择“存储帐户(无)”。
  6. 选择要使用的 Azure 存储帐户。 为获得最佳性能,请使用 Batch 帐户所在区域中的帐户。

保存输出数据

可以使用文件约定库保存作业和任务输出数据。 首先,在 Azure 存储中创建容器。 然后,将输出保存到容器。 在任务代码中使用适用于 .NET 的 Azure 存储客户端库将任务输出上传到该容器。

有关在 Azure 存储中使用容器和 Blob 的详细信息,请参阅通过 .NET 开始使用 Azure Blob 存储

使用文件约定库保存的所有作业和任务输出存储在同一个容器中。 如果大量任务同时尝试保存文件,则可能会强制实施 Azure 存储限制。 有关详细信息,请参阅 Blob 存储的性能和可伸缩性清单

创建存储容器

若要将任务输出保留到 Azure 存储,首先请通过调用 CloudJob.PrepareOutputStorageAsync 创建容器。 此扩展方法采用 CloudStorageAccount 对象作为参数。 该方法创建一个根据文件约定标准命名的容器。 Azure 门户和本文中所述的检索方法可以发现容器的内容。

通常,在客户端应用程序中创建容器,以创建池、作业和任务。 例如:

CloudJob job = batchClient.JobOperations.CreateJob(
    "myJob",
    new PoolInformation { PoolId = "myPool" });

// Create reference to the linked Azure Storage account
CloudStorageAccount linkedStorageAccount =
    new CloudStorageAccount(myCredentials, true);

// Create the blob storage container for the outputs
await job.PrepareOutputStorageAsync(linkedStorageAccount);

存储任务输出

创建存储容器后,任务可以使用 TaskOutputStorage 将输出保存到容器。 此类在文件约定库中可用。

在任务代码中,创建 TaskOutputStorage 对象。 当任务完成其工作时,调用 TaskOutputStorage.SaveAsync 方法。 此步骤会将输出保存到 Azure 存储。

CloudStorageAccount linkedStorageAccount = new CloudStorageAccount(myCredentials);
string jobId = Environment.GetEnvironmentVariable("AZ_BATCH_JOB_ID");
string taskId = Environment.GetEnvironmentVariable("AZ_BATCH_TASK_ID");

TaskOutputStorage taskOutputStorage = new TaskOutputStorage(
    linkedStorageAccount, jobId, taskId);

/* Code to process data and produce output file(s) */

await taskOutputStorage.SaveAsync(TaskOutputKind.TaskOutput, "frame_full_res.jpg");
await taskOutputStorage.SaveAsync(TaskOutputKind.TaskPreview, "frame_low_res.jpg");

TaskOutputStorage.SaveAsync 方法的 kind 参数对保存的文件进行分类。 有四个预定义的 TaskOutputKind 类型:TaskOutputTaskPreviewTaskLogTaskIntermediate.。也可以定义输出的自定义类别。

指定稍后查询 Batch 时要列出的输出类型。 然后,在列出某个任务的输出时,可以根据输出类型之一进行筛选。 例如,根据“提供任务 109 的预览输出”进行筛选。有关详细信息,请参阅检索输出数据

输出类型还确定了输出文件在 Azure 门户中的显示位置。 TaskOutput 类别中的文件位于“任务输出文件”下。 TaskLog 类别中的文件位于“任务日志”下。

存储作业输出

你还可以存储与整个作业关联的输出。 例如,在电影渲染作业的合并任务中,可以将完全渲染的电影保存为作业输出。 作业完成后,客户端应用程序可以列出和检索作业的输出。 客户端应用程序不必查询单个任务。

通过调用 JobOutputStorage.SaveAsync 方法存储作业输出。 指定 JobOutputKind 和文件名。 例如:

CloudJob job = new JobOutputStorage(acct, jobId);
JobOutputStorage jobOutputStorage = job.OutputStorage(linkedStorageAccount);

await jobOutputStorage.SaveAsync(JobOutputKind.JobOutput, "mymovie.mp4");
await jobOutputStorage.SaveAsync(JobOutputKind.JobPreview, "mymovie_preview.mp4");

与用于任务输出的 TaskOutputKind 类型一样,可以使用 JobOutputKind 类型对作业的已保存文件分类。 稍后,可以列出特定类型的输出。 JobOutputKind 类型包括输出和预览类别。 该类型还支持创建自定义类别。

存储任务日志

你可能还需要保存在任务执行期间更新的文件。 例如,你可能需要保存日志文件或 stdout.txtstderr.txt。 文件约定库提供 TaskOutputStorage.SaveTrackedAsync 方法来保存这些类型的文件。 使用 SaveTrackedAsync 以指定的时间间隔跟踪节点上文件的更新。 然后,将这些更新保存到 Azure 存储。

以下示例在执行任务期间,每隔 15 秒使用 SaveTrackedAsync 更新 Azure 存储中的 stdout.txt

TimeSpan stdoutFlushDelay = TimeSpan.FromSeconds(3);
string logFilePath = Path.Combine(
    Environment.GetEnvironmentVariable("AZ_BATCH_TASK_DIR"), "stdout.txt");

// The primary task logic is wrapped in a using statement that sends updates to
// the stdout.txt blob in Storage every 15 seconds while the task code runs.
using (ITrackedSaveOperation stdout =
        await taskStorage.SaveTrackedAsync(
        TaskOutputKind.TaskLog,
        logFilePath,
        "stdout.txt",
        TimeSpan.FromSeconds(15)))
{
    /* Code to process data and produce output file(s) */

    // We are tracking the disk file to save our standard output, but the
    // node agent may take up to 3 seconds to flush the stdout stream to
    // disk. So give the file a moment to catch up.
     await Task.Delay(stdoutFlushDelay);
}

将注释部分 Code to process data and produce output file(s) 替换为任务通常执行的任何代码。 例如,代码可能会从 Azure 存储下载数据,然后对其执行转换或计算。 你可以将此代码包装在 using 块中,以使用 SaveTrackedAsync 定期更新文件。

节点代理是在池中的每个节点上运行的程序。 该程序在节点和 Batch 服务之间提供命令和控制接口。 此 using 块的末尾需要 Task.Delay 调用。 该调用确保节点代理有时间将标准的内容刷新到节点上的 stdout.txt 文件。 若没有此延迟,可能会遗漏最后几秒的输出。 对于所有文件,可能不需要此延迟。

启用 SaveTrackedAsync 文件跟踪时,只会在 Azure 存储中保存被跟踪文件的追加内容。 此方法只用于跟踪非轮转的日志文件或使用追加操作写入文件末尾的其他文件。

检索输出数据

若要检索特定任务或作业的输出文件,你无需知道 Azure 存储中的路径或文件名。 可以按任务 ID 或作业 ID 请求输出文件。

以下示例代码将循环访问作业的任务。 接着,代码会打印有关任务输出文件的一些信息。 然后,代码从 AzureStorage 下载文件。

foreach (CloudTask task in myJob.ListTasks())
{
    foreach (OutputFileReference output in
        task.OutputStorage(storageAccount).ListOutputs(
            TaskOutputKind.TaskOutput))
    {
        Console.WriteLine($"output file: {output.FilePath}");

        output.DownloadToFileAsync(
            $"{jobId}-{output.FilePath}",
            System.IO.FileMode.Create).Wait();
    }
}

在 Azure 门户中查看输出文件

如果任务输出文件使用 Batch 文件约定标准,你可以在 Azure 门户中查看这些文件。

若要在门户中显示输出文件,必须满足以下要求:

若要在 Azure 门户中自动显示输出文件,你必须:

  1. 将 Azure 存储帐户关联到 Batch 帐户
  2. 遵循 Azure 存储容器和文件的预定义命名约定。 有关所有定义,请查看自述文件。 如果使用文件约定库保存输出,则按文件约定标准来保存文件。

若要在 Azure 门户中查看任务输出文件和日志,请执行以下操作:

  1. 登录 Azure 门户
  2. 转到要查看其输出的任务。
  3. 选择“已保存的输出文件”或“已保存的日志” 。

代码示例

PersistOutputs 示例项目是 GitHub 上的 Azure Batch 代码示例之一。 此 Visual Studio 解决方案介绍如何使用 Azure Batch 文件约定库将任务输出保存到持久性存储。 若要运行该示例,请遵循以下步骤:

  1. 在 Visual Studio 2019 中打开项目。
  2. 将 Batch 和 Azure 存储帐户凭据添加到 Microsoft.Azure.Batch.Samples.Common 项目中的 AccountSettings.settings。
  3. 生成解决方案。 先不要运行解决方案。
  4. 根据提示还原所有 NuGet 包。
  5. 通过 Azure 门户上传 PersistOutputsTask 的应用程序包
    1. 在 .zip 包中包含 PersistOutputsTask.exe 可执行文件及其依赖程序集。
    2. 将应用程序 ID 设置为 PersistOutputsTask
    3. 将应用程序包版本设置为 1.0
  6. 选择“启动”运行项目。
  7. 当系统提示选择要使用的保存技术时,请输入 1。 此选项使用文件约定库运行示例,以保存任务输出。

获取适用于 .NET 的 Batch 文件约定库

NuGet 上提供了适用于 .NET 的 Batch 文件约定库。 该库使用新方法扩展了 CloudJobCloudTask 类。 有关详细信息,请参阅文件约定库参考文档

GitHub 上提供了文件约定库源代码

后续步骤