Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
在Azure Batch中运行的任务可能会在运行时生成输出数据。 通常需要存储任务输出数据,以便作业中的其他任务和/或执行该作业的客户端应用程序进行检索。 任务将输出数据写入 Batch 计算节点的文件系统,但当节点被重置映像或从池中移除时,节点上的数据将会丢失。 任务可能还具有文件保留期,超过此保留期后,系统将删除该任务创建的文件。 出于这些原因,请务必将稍后需要的任务输出保存到数据存储(如 Azure Storage)。
有关 Batch 中的存储帐户选项,请参阅 Batch 帐户和 Azure Storage 帐户。
Batch 服务 API 支持将运行于具有 Virtual Machine Configuration 的池上的任务和作业管理器任务的输出数据持久化到 Azure Storage。 添加任务时,可以在Azure Storage中指定容器作为任务输出的目标。 然后,在完成该任务时,Batch 服务会将所有输出数据写入该容器。
如果使用 Batch 服务 API 保存任务输出,你将无需修改任务运行的应用程序。 只需对客户端应用程序进行几处修改,即可从创建任务的同一代码内部保存任务的输出。
重要
使用 Batch 服务 API 将任务数据持久化到 Azure Storage 不适用于在 2018 年 2 月 1 日 之前创建的池。
何时使用 Batch 服务 API 保存任务输出?
Azure Batch提供了多个保存任务输出的方法。 使用 Batch 服务 API 是一种便捷的方法,最适合以下情况:
- 希望编写代码来从客户端应用程序内部保存任务输出,而无需修改任务运行的应用程序。
- 您希望在使用虚拟机配置创建的池中保留 Batch 任务和作业管理器任务的输出。
- 想要将输出保存到具有任意名称的Azure Storage容器。
- 你希望根据 Batch 文件约定标准将输出保存到名为Azure Storage容器。
如果你的情况与上面不同,可能需要考虑不同的方法。 例如,Batch 服务 API 当前不支持在任务运行时将流式输出流式传输到Azure Storage。 若要流式传输输出,请考虑使用可用于.NET的 Batch 文件约定库。 对于其他语言,需要实现自己的解决方案。 有关其他选项的详细信息,请参阅 Persist 作业和任务输出到 Azure Storage。
在 Azure Storage 中创建容器
若要将任务输出保存到Azure Storage,需要创建一个容器,用作输出文件的目标。 在运行任务之前创建容器,最好是在提交作业之前,使用适当的Azure Storage客户端库或 SDK。 有关Azure Storage API 的详细信息,请参阅 Azure Storage 文档。
例如,如果您正在用 C# 编写应用程序,请使用 用于 .NET 的 Azure Storage 客户端库。 以下示例演示如何创建容器:
CloudBlobContainer container = storageAccount.CreateCloudBlobClient().GetContainerReference(containerName);
await container.CreateIfNotExists();
指定任务输出的输出文件
若要指定任务的输出文件,请在创建任务时创建一组 OutputFile 对象并将其分配给 CloudTask.OutputFiles 属性。 可以使用共享访问签名(SAS)或托管标识对容器访问进行身份验证。
使用共享访问签名
创建容器后,获取具有对容器写入权限的共享访问签名(SAS)。 SAS 允许对容器进行委托访问。 SAS 根据指定的一组权限和指定的时间间隔授予访问权限。 Batch 服务需要拥有写入权限的 SAS,才能将任务输出写入到容器。 有关 SAS 的详细信息,请参阅 Azure 存储中的共享访问签名 (SAS) 的使用。
使用 Azure Storage API 获取 SAS 时,API 将返回 SAS 令牌字符串。 此令牌字符串包含 SAS 的所有参数,其中包括权限以及 SAS 的生效间隔。 若要使用 SAS 访问 Azure 存储中的容器,需要将 SAS 令牌字符串追加到资源 URI。 资源 URI 与附加的 SAS 令牌一起提供对 Azure Storage 的经过身份验证的访问。
以下示例演示如何获取容器的只写 SAS 令牌字符串,然后将 SAS 追加到容器 URI:
string containerSasToken = container.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddDays(1),
Permissions = SharedAccessBlobPermissions.Write
});
string containerSasUrl = container.Uri.AbsoluteUri + containerSasToken;
以下 C# 代码示例创建可将随机数写入名为 output.txt 的文件的任务。 该示例为要写入容器的 output.txt 创建输出文件。 该示例还为匹配文件模式 std*.txt(例如 和 stdout.txt)的所有日志文件创建输出文件。 容器 URL 需要先前为容器创建的 SAS。 Batch 服务使用 SAS 对容器的访问进行身份验证。
new CloudTask(taskId, "cmd /v:ON /c \"echo off && set && (FOR /L %i IN (1,1,100000) DO (ECHO !RANDOM!)) > output.txt\"")
{
OutputFiles = new List<OutputFile>
{
new OutputFile(
filePattern: @"..\std*.txt",
destination: new OutputFileDestination(
new OutputFileBlobContainerDestination(
containerUrl: containerSasUrl,
path: taskId)),
uploadOptions: new OutputFileUploadOptions(
uploadCondition: OutputFileUploadCondition.TaskCompletion)),
new OutputFile(
filePattern: @"output.txt",
destination:
new OutputFileDestination(new OutputFileBlobContainerDestination(
containerUrl: containerSasUrl,
path: taskId + @"\output.txt")),
uploadOptions: new OutputFileUploadOptions(
uploadCondition: OutputFileUploadCondition.TaskCompletion)),
}
注意事项
如果在 Linux 中使用此示例,请务必将反斜杠更改为正斜杠。
使用托管标识
托管标识可以用于与 Azure 存储进行身份验证,而不是通过生成和传递具有写入权限的 SAS 到 Batch。 该标识必须分配给 Batch 池,并且还必须具有对要写入的容器的Storage Blob Data Contributor角色分配权限。 然后,可以告知 Batch 服务使用托管标识而不是 SAS 来验证对容器的访问权限。
CloudBlobContainer container = storageAccount.CreateCloudBlobClient().GetContainerReference(containerName);
await container.CreateIfNotExists();
new CloudTask(taskId, "cmd /v:ON /c \"echo off && set && (FOR /L %i IN (1,1,100000) DO (ECHO !RANDOM!)) > output.txt\"")
{
OutputFiles = new List<OutputFile>
{
new OutputFile(
filePattern: @"..\std*.txt",
destination: new OutputFileDestination(
new OutputFileBlobContainerDestination(
containerUrl: container.Uri,
path: taskId,
identityReference: new ComputeNodeIdentityReference() { ResourceId = "/subscriptions/SUB/resourceGroups/RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/identity-name"} })),
uploadOptions: new OutputFileUploadOptions(
uploadCondition: OutputFileUploadCondition.TaskCompletion))
}
}
指定用于匹配的文件模式
指定输出文件时,可以使用 OutputFile.FilePattern 属性指定用于匹配的文件模式。 文件模式可以匹配零个文件、一个文件或者任务创建的一组文件。
FilePattern 属性支持标准文件系统通配符,例如 *(表示非递归匹配)和 **(表示递归匹配)。 例如,上述代码示例指定要以非递归方式匹配 std*.txt 的文件模式:
filePattern: @"..\std*.txt"
若要上传单个文件,请指定不带通配符的文件模式。 例如,上述代码示例指定用于匹配 output.txt 的文件模式:
filePattern: @"output.txt"
指定上传条件
OutputFileUploadOptions.UploadCondition 属性允许条件上传输出文件。 一种常见方案是任务成功时上传一组文件,任务失败时上传另一组文件。 例如,你可能希望仅当任务失败并使用非零退出代码退出时,才上传详细日志文件。 同样,你可能希望仅当任务成功时才上传结果文件,因为任务失败时这些文件可能会丢失或不完整。
上述代码示例将 UploadCondition 属性设置为 TaskCompletion。 此设置指定在任务完成后上传文件,不管退出代码的值是什么。
uploadCondition: OutputFileUploadCondition.TaskCompletion
有关其他设置,请参阅 OutputFileUploadCondition 枚举。
区分同名的文件
作业中的任务可能会生成同名的文件。 例如,对于作业中运行的每个任务,都会创建 stdout.txt 和 stderr.txt。 由于每个任务在其自身的上下文中运行,因此这些文件在节点的文件系统中不会冲突。 但是,在将多个任务生成的文件上传到共享容器时,需要区分同名的文件。
OutputFileBlobContainerDestination.Path 属性指定输出文件的目标 blob 或虚拟目录。 可以使用 Path 属性以这样的方式命名 blob 或虚拟目录,以确保输出的同名文件在 Azure Storage 中有唯一名称。 在路径中使用任务 ID 是一种很好的做法,可以确保名称唯一,同时轻松识别文件。
如果 FilePattern 属性设置为通配符表达式,则与模式匹配的所有文件将上传到 Path 属性指定的虚拟目录。 例如,如果容器为 mycontainer,则任务 ID 为 mytask,并且文件模式为 ..\std*.txt,则Azure Storage中输出文件的绝对 URI 将类似于:
https://myaccount.blob.core.chinacloudapi.cn/mycontainer/mytask/stderr.txt
https://myaccount.blob.core.chinacloudapi.cn/mycontainer/mytask/stdout.txt
如果 FilePattern 属性设置为匹配单个文件名(意味着不包含任何通配符),则 Path 属性的值将指定完全限定的 Blob 名称。 如果预期命名会与多个任务生成的单个文件相冲突,在文件名中包含虚拟目录的名称即可区分这些文件。 例如,将 Path 属性设置为包含任务 ID、分隔符(通常是正斜杠)和文件名:
path: taskId + @"/output.txt"
一组任务的输出文件的绝对 URI 类似于:
https://myaccount.blob.core.chinacloudapi.cn/mycontainer/task1/output.txt
https://myaccount.blob.core.chinacloudapi.cn/mycontainer/task2/output.txt
有关 Azure Storage 中的虚拟目录的详细信息,请参阅 在容器中列出 blob。
很多输出文件
当任务指定大量输出文件时,可能会遇到Azure Batch API 施加的限制。 建议保持任务较小,并将输出文件的数量保持较低。
如果遇到限制,请考虑使用文件模式或使用文件容器(例如 tar 或 zip)来合并输出文件,从而减少输出文件的数量。 或者,使用挂载或其他方法来持久化数据输出(请参阅持久化作业和任务输出)。
诊断文件上传错误
如果将输出文件上传到 Azure Storage 失败,任务将转为 Completed 状态,并且 TaskExecutionInformation.FailureInformation 属性被设置。 检查 FailureInformation 属性可确定发生了哪种错误。 例如,下面是在找不到容器的情况下,上传文件时发生的错误:
Category: UserError
Code: FileUploadContainerNotFound
Message: One of the specified Azure container(s) was not found while attempting to upload an output file
每次上传文件时,Batch 都会将以下两个日志文件写入计算节点:fileuploadout.txt 和 fileuploaderr.txt。 可以检查这些日志文件来详细了解具体的失败情况。 如果从未尝试上传文件(例如,因为任务本身无法运行),则这些日志文件不会存在。
诊断文件上传的性能
fileuploadout.txt 文件记录了上传进度。 可以检查此文件来详细了解上传文件所花费的时间。 请记住,上传性能有许多因素,包括节点大小、上传时节点上的其他活动、目标容器是否与 Batch 池位于同一区域、同时上传到storage帐户的节点数等。
结合 Batch 文件约定标准使用 Batch 服务 API
使用 Batch 服务 API 保存任务输出时,可以根据喜好为目标容器和 Blob 命名。 还可以根据 Batch 文件约定标准选择命名它们。 文件约定标准根据作业和任务的名称确定给定输出文件Azure Storage中目标容器和 blob 的名称。 如果使用文件约定标准来命名输出文件,则输出文件可用于在 Azure portal 中查看。
如果您使用 C# 进行开发,可以使用 用于 .NET 的 Batch 文件约定库 中提供的方法。 此库将为你创建适当命名的容器和 Blob 路径。 例如,可以调用 API 根据作业名称来获取容器的正确名称:
string containerName = job.OutputStorageContainerName();
可以使用 CloudJobExtensions.GetOutputStorageContainerUrl 方法返回用于写入容器的共享访问签名(SAS)URL。 然后,可以将此 SAS 传递给 OutputFileBlobContainerDestination 构造函数。
如果使用除 C# 以外的语言进行开发,则需要自行实现文件约定标准。
代码示例
PersistOutputs 示例项目是 GitHub 上 Azure Batch 代码示例 中的一个。 此 Visual Studio 解决方案演示如何使用适用于 .NET 的 Batch 客户端库,将任务输出保存到持久存储。 若要运行该示例,请遵循以下步骤:
- 在 Visual Studio 2019 中打开项目。
- 将 Batch 和 Storage account 凭据添加到 Microsoft.Azure.Batch.Samples.Common 项目的 AccountSettings.settings 中。
- 生成(但不要运行)该解决方案。 根据提示还原所有 NuGet 包。
- 使用Azure门户上传应用包供PersistOutputsTask使用。 在 .zip 包中包含
PersistOutputsTask.exe及其依赖程序集,将应用程序 ID 设置为“PersistOutputsTask”,将应用程序包版本设置为“1.0”。 - 启动并运行PersistOutputs 项目。
- 当系统提示选择用于运行示例的持久性技术时,请输入 2,以运行使用 Batch 服务 API 保存任务输出的示例。
- 如果需要,请输入 3 再次运行示例,以使用 Batch 服务 API 保存输出,并根据文件约定标准将目标容器和 Blob 路径命名。
后续步骤
- 若要详细了解如何使用适用于 .NET 的文件约定库持久化任务输出,请参阅 利用适用于 .NET 的 Batch 文件约定库将作业和任务数据持久化到 Azure Storage。
- 若要了解在Azure Batch中保存输出数据的其他方法,请参阅 Persist 作业和任务输出到 Azure Storage。