你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

创建可高效列出 Batch 资源的查询

大多数 Azure Batch 应用程序执行监视或查询 Batch 服务的其他操作。 此类列表查询通常定期发生。 例如,必须先获取作业中每项任务的数据,然后才能查看该作业中排队的任务。 减少 Batch 服务为查询返回的数据量可提升应用程序的性能。 本文介绍如何以有效的方式创建和执行此类查询。 可以使用 Batch .NET 库为 Batch 作业、任务、计算节点和其他资源创建筛选的查询。

注意

Batch 服务为作业中的任务计数以及 Batch 池中的计算节点计数这类常见方案提供 API 支持。 可以调用获取任务计数列出池节点计数操作,而不是使用列表查询。 但是,这些更高效的操作会返回更有限的信息,这些信息可能不是最新的。 有关详细信息,请参阅按状态对任务和计算节点计数

指定详细信息级别

生产型 Batch 应用程序可包含成千上万个作业、任务和计算节点等实体。 对于有关资源的每个查询,可能会从 Batch 服务向应用程序传输大量数据。 限制查询返回的项数和信息类型,以提升性能。

Batch .NET API 代码片段列出了与作业关联的每项任务,以及每项任务的所有属性。

// Get a collection of all of the tasks and all of their properties for job-001
IPagedEnumerable<CloudTask> allTasks =
    batchClient.JobOperations.ListTasks("job-001");

向查询应用详细信息级别,以更高效地列出信息。 向 JobOperations.ListTasks 方法提供 ODATADetailLevel 对象。 此代码片段仅返回已完成任务的 ID、命令行和计算节点信息属性。

// Configure an ODATADetailLevel specifying a subset of tasks and
// their properties to return
ODATADetailLevel detailLevel = new ODATADetailLevel();
detailLevel.FilterClause = "state eq 'completed'";
detailLevel.SelectClause = "id,commandLine,nodeInfo";

// Supply the ODATADetailLevel to the ListTasks method
IPagedEnumerable<CloudTask> completedTasks =
    batchClient.JobOperations.ListTasks("job-001", detailLevel);

在此示例方案中,如果作业中存在数以千计的任务,则通常情况下,第二个查询的结果的返回速度将快于第一个查询。 若要详细了解使用 Batch .NET API 列出项时如何使用 ODATADetailLevel,请参阅在 Batch .NET 中进行高效查询部分。

重要

强烈建议始终将 ODATADetailLevel 对象提供给 .NET API 列表调用,以便最大程度地提高应用程序的效率和性能。 指定详细程度有助于缩短 Batch 服务响应时间、提高网络利用率,以及最大程度减少客户端应用程序的内存使用量。

使用查询字符串

可以使用 Batch .NETBatch REST API 减少查询返回的项数,以及查询针对每个项返回的信息量。 可以使用三种查询字符串类型来缩小查询范围:$filter$select$expand

有关 Batch .NET API,请参阅 ODATADetailLevel 类属性。 另请查看在 Batch .NET 中进行高效查询部分。

有关 Batch REST API,请参阅 Batch REST API 参考。 找到要查询的资源的列表参考。 然后,查看“URI 参数”部分,了解关于 $filter$select$expand 的详细信息。 有关示例,请参阅池的 URI 参数 - 列表。 另请参阅如何使用 Azure CLI 进行高效的 Batch 查询

注意

构造这三种查询字符串类型中的任意一种类型时,必须确保属性名称和大小写与其 REST API 元素的对应项相匹配。 例如,在使用 .NET CloudTask 类时,必须指定 state 而非 State,即使 .NET 属性为 CloudTask.State。 有关详细信息,请参阅 .NET 和 REST API 之间的属性映射

筛选器

$filter 表达式字符串用于减少返回的项数。 例如,可以只列出作业的正在运行的任务,或者只列出已准备好来运行任务的计算节点。

此字符串包含一个或多个表达式,其中一个表达式包含属性名称、运算符和值。 能够指定哪些属性取决于所查询的每个实体类型,每个属性所支持的运算符也是这样。 可以使用逻辑运算符 andor 将多个表达式组合到一起。

此示例仅列出正在运行的呈现任务:(state eq 'running') and startswith(id, 'renderTask')

选择

$select 表达式字符串用于限制针对每个项返回的属性值。 可以指定以逗号分隔的属性名称列表,并且仅针对查询结果中的项返回这些属性值。 可以指定所查询的实体类型的任意属性。

此示例指定每项任务只应返回三个属性值:id, state, stateTransitionTime

展开

$expand 表达式字符串用于减少获取特定信息所需的 API 调用数。 可以使用此字符串通过单个 API 调用获取有关每个项的详细信息。 此方法通过减少 API 调用来帮助提升性能。 使用 $expand 字符串,而不是获取实体列表并请求有关每个列表项的信息。

$select 类似,$expand 用于控制是否将某些数据包括在列表查询结果中。 当所有属性都是必需属性且未指定 select 字符串时,必须使用 $expand 来获取统计信息。 如果使用了 select 字符串来获取属性的子集,则可在 select 字符串中指定 stats,不需指定 $expand

支持使用此字符串列出作业、作业计划、任务和池。 目前,此字符串仅支持统计信息。

此示例指定应为列表中的每个项返回统计信息:stats

filter、select 和 expand 字符串的规则

  • 请确保 filter、select 和 expand 字符串中显示的属性名称以同样的方式显示在 Batch REST API 中。 即使使用 Batch .NET 或其他 Batch SDK 之一,此规则也适用。
  • 所有属性名称均区分大小写,但属性值不区分大小写。
  • 日期/时间字符串可以采用两种格式中的一种,并且必须在前面加上 DateTime
    • W3C-DTF 格式示例:creationTime gt DateTime'2011-05-08T08:49:37Z'
    • RFC 1123 格式示例:creationTime gt DateTime'Sun, 08 May 2011 08:49:37 GMT'
  • 布尔值字符串为 truefalse
  • 如果指定了无效的属性或运算符,则会导致 400 (Bad Request) 错误。

在 Batch .NET 中进行高效查询

Batch .NET API 中,ODATADetailLevel 类提供用于列出操作的 filter、select 和 expand 字符串ODataDetailLevel 类具有三个公共字符串属性。 可以在构造函数中指定这些属性,也可以直接在对象上设置这些属性。 然后,可将 ODataDetailLevel 对象作为参数传递给不同的列表操作,例如 ListPoolsListJobsListTasks

以下代码片段使用 Batch .NET API 对 Batch 服务进行高效查询,查询其中是否存在特定池集的统计信息。 Batch 用户既有测试池又有生产池。 测试池 ID 具有“test”前缀,生产池 ID 具有“prod”前缀。 myBatchClient 是正确初始化的 BatchClient 类实例。

// First we need an ODATADetailLevel instance on which to set the filter, select,
// and expand clause strings
ODATADetailLevel detailLevel = new ODATADetailLevel();

// We want to pull only the "test" pools, so we limit the number of items returned
// by using a FilterClause and specifying that the pool IDs must start with "test"
detailLevel.FilterClause = "startswith(id, 'test')";

// To further limit the data that crosses the wire, configure the SelectClause to
// limit the properties that are returned on each CloudPool object to only
// CloudPool.Id and CloudPool.Statistics
detailLevel.SelectClause = "id, stats";

// Specify the ExpandClause so that the .NET API pulls the statistics for the
// CloudPools in a single underlying REST API call. Note that we use the pool's
// REST API element name "stats" here as opposed to "Statistics" as it appears in
// the .NET API (CloudPool.Statistics)
detailLevel.ExpandClause = "stats";

// Now get our collection of pools, minimizing the amount of data that is returned
// by specifying the detail level that we configured above
List<CloudPool> testPools =
    await myBatchClient.PoolOperations.ListPools(detailLevel).ToListAsync();

提示

使用 Select 和 Expand 子句配置的 ODATADetailLevel 实例也可以传递给相应的 Get 方法(例如 PoolOperations.GetPool),以便限制返回的数据量。

Batch REST 到 .NET API 映射

filter、select 和 expand 字符串中的属性名称必须反映其 REST API 对应项,不管是名称本身还是大小写。 下表提供了 .NET 和 REST API 的对应项之间的映射。

filter 字符串的映射

  • .NET 列表方法:此列中的每个 .NET API 方法都接受 ODATADetailLevel 对象作为参数。
  • REST 列表请求:此列中列出的每个 REST API 页面都包含一个表,其中包含 filter 字符串中允许的属性和操作。 在构造 ODATADetailLevel.FilterClause 字符串时,可使用这些属性名称和操作。
.NET 列表方法 REST 列表请求
CertificateOperations.ListCertificates 列出帐户中的证书
CloudTask.ListNodeFiles 列出与任务关联的文件
JobOperations.ListJobPreparationAndReleaseTaskStatus 列出作业准备状态以及作业的作业版本任务
JobOperations.ListJobs 列出帐户中的作业
JobOperations.ListNodeFiles 列出节点上的文件
JobOperations.ListTasks 列出与作业关联的任务
JobScheduleOperations.ListJobSchedules 列出帐户中的作业计划
JobScheduleOperations.ListJobs 列出与作业计划关联的作业
PoolOperations.ListComputeNodes 列出池中的计算节点
PoolOperations.ListPools 列出帐户中的池

select 字符串的映射

  • Batch.NET 类型:Batch.NET API 类型。
  • REST API 实体:此列中的每一页都包含一个或多个表,其中列出了类型的 REST API 属性名称。 在构造 select 字符串时使用这些属性名称。 在构造 ODATADetailLevel.SelectClause 字符串时,将使用这些相同的属性名称。
Batch .NET 类型 REST API 实体
证书 获取有关证书的信息
CloudJob 获取有关作业的信息
CloudJobSchedule 获取有关作业计划的信息
ComputeNode 获取有关节点的信息
CloudPool 获取有关池的信息
CloudTask 获取有关任务的信息

示例:构造 filter 字符串

若要构造 filter 字符串 ODATADetailLevel.FilterClause,请找到相应的 REST API 页面。 可选择属性及其支持的运算符位于第一个多行表中。 例如,若要检索其退出代码不为零的所有任务,可查看列出与作业相关联的任务,以了解相应的属性字符串以及允许的运算符:

属性 允许的操作 类型
executionInfo/exitCode eq, ge, gt, le , lt Int

相关的 filter 字符串是:

(executionInfo/exitCode lt 0) or (executionInfo/exitCode gt 0)

示例:构造 select 字符串

若要构造 ODATADetailLevel.SelectClause,请找到所列实体的相应的 REST API 页面。 可选择属性及其支持的运算符位于第一个多行表中。 例如,若要仅检索列表中每项任务的 ID 和命令行,请查看获取有关任务的信息

属性 类型 注释
id String The ID of the task.
commandLine String The command line of the task.

相关的 select 字符串是:

id, commandLine

代码示例

高效列表查询

EfficientListQueries 示例项目显示了高效的列表查询对应用程序性能的影响。 此 C# 控制台应用程序创建大量的任务并将其添加到作业。 然后,应用程序对 JobOperations.ListTasks 方法进行多次调用并传递 ODATADetailLevel 对象。 这些对象配置有不同的属性值,以改变要返回的数据量。 此示例生成类如下输出:

Adding 5000 tasks to job jobEffQuery...
5000 tasks added in 00:00:47.3467587, hit ENTER to query tasks...

4943 tasks retrieved in 00:00:04.3408081 (ExpandClause:  | FilterClause: state eq 'active' | SelectClause: id,state)
0 tasks retrieved in 00:00:00.2662920 (ExpandClause:  | FilterClause: state eq 'running' | SelectClause: id,state)
59 tasks retrieved in 00:00:00.3337760 (ExpandClause:  | FilterClause: state eq 'completed' | SelectClause: id,state)
5000 tasks retrieved in 00:00:04.1429881 (ExpandClause:  | FilterClause:  | SelectClause: id,state)
5000 tasks retrieved in 00:00:15.1016127 (ExpandClause:  | FilterClause:  | SelectClause: id,state,environmentSettings)
5000 tasks retrieved in 00:00:17.0548145 (ExpandClause: stats | FilterClause:  | SelectClause: )

Sample complete, hit ENTER to continue...

示例显示了限制返回的属性和项数可以大幅缩短查询响应时间。 可以在 GitHub 的 azure-batch-samples 存储库中查找此项目和其他示例项目。

BatchMetrics 库

下列 BatchMetrics 示例项目演示了如何使用 Batch API 有效地监视 Azure Batch 作业进度。

此示例包括一个 .NET 类库项目,可将其合并到自己的项目中。 还有一个简单的命令行程序,可用于练习和演示库的用途。

项目中的示例应用程序演示了以下操作:

  • 选择特定属性即可只下载所需属性
  • 若只下载自上次查询以来发生更改的内容,可针对状态转换时间进行筛选

例如,以下方法会显示在 BatchMetrics 库中。 它会返回 ODATADetailLevel,指定仅针对所查询的实体获取 idstate 属性。 它还指定只应返回其状态自指定 DateTime 参数以来发生更改的实体。

internal static ODATADetailLevel OnlyChangedAfter(DateTime time)
{
    return new ODATADetailLevel(
        selectClause: "id, state",
        filterClause: string.Format("stateTransitionTime gt DateTime'{0:o}'", time)
    );
}

后续步骤