Эффективное создание запросов на вывод списка ресурсов пакетной службы

Большинство приложений пакетной службы Azure выполняют мониторинг или другие операции, запрашивающие пакетную службу. Такие запросы списков часто выполняются через регулярные интервалы. Например, прежде чем проверять наличие задач в очереди в задании, необходимо получить данные о каждой задаче в этом задании. Уменьшение объема данных, возвращаемых пакетной службой для запросов, повышает производительность приложения. В этой статье объясняется, как создавать и выполнять такие запросы наиболее эффективно. Вы можете создавать отфильтрованные запросы для заданий пакетной службы, задач, вычислительных узлов и других ресурсов с помощью библиотеки .NET пакетной службы.

Примечание

Пакетная служба поддерживает API для распространенных сценариев подсчета задач в задании и вычислительных узлов в пуле пакетной службы. Вместо того чтобы использовать запрос на вывод списка, вы можете вызвать операции "Получить количество задач" и "Вывести количество узлов в пуле". Однако эти более эффективные операции возвращают более ограниченную информацию, которая может быть неактуальной. Подробнее см. в разделе Подсчет задач и вычислительных узлов с определенным состоянием.

Определение уровня детализации

В рабочем приложении пакетной службы такие сущности, как задания, задачи и вычислительные узлы, могут исчисляться тысячами. Для каждого запроса, который вы делаете о ресурсах, потенциально большой объем данных передается из пакетной службы в приложение. Ограничьте количество элементов и сведения, возвращаемые запросом, чтобы повысить производительность.

Этот фрагмент кода API пакетной службы .NET перечисляет все задачи, связанные с заданием, а также выводит полный набор их свойств.

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

Применяйте к запросу уровень детализации для более эффективного перечисления сведений. Для этого необходимо передать объект ODATADetailLevel методу JobOperations.ListTasks. Этот фрагмент кода возвращает только идентификатор, командную строку и информационные свойства вычислительного узла только для завершенных задач.

// 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);

Если, как в данном примере сценария, задание состоит из тысяч задач, результаты для второго запроса обычно возвращаются быстрее, чем для первого. Дополнительные сведения об использовании ODATADetailLevel при перечислении элементов с помощью API пакетной службы .NET см. в разделе "Эффективные запросы в пакетной службе .NET".

Важно!

Мы настоятельно рекомендуем всегда передавать объект ODATADetailLevel в вызовы API .NET для получения списков. Это обеспечит максимальную эффективность и производительность приложения. Задание уровня детализации помогает снизить время ответа пакетной службы, повысить эффективность использования сети и минимизировать использование памяти клиентскими приложениями.

Использование строк запроса

Вы можете использовать API пакетной службы .NET и пакетной службы REST, чтобы уменьшить количество элементов, возвращаемых запросом, и объем сведений, возвращаемых запросом для каждого элемента. Существует три типа строк запроса, которые можно использовать для сужения запроса: $filter, $select и $expand.

Сведения об API пакетной службы .NET см. в свойствах класса ODATADetailLevel. Кроме того, ознакомьтесь с разделом "Эффективные запросы в пакетной службе .NET".

Сведения об API пакетной службы REST см. в справочнике по API пакетной службы REST. Найдите ссылку на список для ресурса, который требуется запросить. Затем просмотрите раздел "Параметры URI" для получения дополнительных сведений о $filter, $select, и $expand. Например, см. параметры URI для пула — список. Кроме того, узнайте как эффективно выполнять пакетные запросы с помощью Azure CLI.

Примечание

При создании какого-либо из трех типов строк запроса необходимо убедиться, что имена и регистр свойств совпадают с аналогичными элементами REST API. Например, при работе с классом CloudTask в .NET необходимо указывать свойство state, а не State, несмотря на то что в .NET используется свойство CloudTask.State. Дополнительные сведения см. в сопоставлении свойств между .NET и REST API.

Фильтр

Строка выражения $filter уменьшает число возвращаемых элементов. Например, можно вывести список только выполняющихся задач в задании или только вычислительных узлов, которые готовы к выполнению задач.

Строка состоит из одного или нескольких выражений, каждое из которых состоит из имени свойства, оператора и значения. Для каждого опрашиваемого типа сущности можно указать только определенные свойства, а также только определенные операторы, поддерживаемые каждым свойством. Несколько выражений можно объединить с помощью логических операторов and и or.

В этом примере выводятся только запущенные задачи отрисовки: (state eq 'running') and startswith(id, 'renderTask').

Выберите пункт

Строка выражения $select ограничивает значения свойств, возвращаемых для каждого элемента. Вы указываете список имен свойств через запятую, после чего в результатах запроса возвращаются только значения указанных свойств для соответствующих элементов. Для запрашиваемого типа сущности можно указать любые свойства.

В этом примере показано, что для каждой задачи необходимо вернуть значения только трех свойств: id, state, stateTransitionTime.

Разверните

Строка выражения $expand сокращает количество вызовов API, необходимое для получения определенных сведений. Эту строку можно использовать для получения дополнительных сведений о каждом элементе с помощью одного вызова API. Этот метод помогает повысить производительность за счет сокращения вызовов API. Используйте строку $expand вместо получения списка сущностей и запроса сведений о каждом элементе списка.

Как и $select, $expand определяет, какие данные нужно включить в результаты запроса списка. Если необходимы все свойства, и строка выборки не указана, для получения статистических данных следует использовать $expand. Если для получения подмножества свойств используется строка выборки, то в ней можно указать stats и не указывать $expand.

Поддерживаемые варианты использования этой строки включают перечисление заданий, расписаний заданий, задач и пулов. В настоящее время строка поддерживает только статистические данные.

В этом примере показано, что для каждого элемента в списке необходимо вернуть статистические данные: stats.

Правила строк фильтрации, выборки и развертывания

  • Убедитесь, что имена свойств в фильтре, строке выборки и строке развертывания отображаются так же, как и в API пакетной службы REST. Это правило применяется даже при использовании пакетной службы .NET или одного из пакетов 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'
  • Строки с логическими выражениями должны иметь значение true или false.
  • Если задано недопустимое свойство или оператор, отобразится ошибка 400 (Bad Request) .

Эффективное выполнение запросов в пакетной службе для .NET

В API пакетной службы .NET для указания строк фильтрации, выборки и развертывания операций списка используется класс ODATADetailLevel. Класс ODataDetailLevel имеет три открытых строковых свойства. Вы можете указать эти свойства в конструкторе или задать свойства непосредственно в объекте. Затем передайте объект ODataDetailLevel в качестве параметра в различные операции получения списка, такие как ListPools, ListJobs и ListTasks.

  • ODATADetailLevel.FilterClause ограничивает количество возвращаемых элементов.
  • ODATADetailLevel.SelectClause определяет, значения каких свойств необходимо вернуть для каждого элемента.
  • ODATADetailLevel.ExpandClause извлекает данные по всем элементам за один вызов API вместо того, чтобы выполнять отдельные вызовы для каждого элемента.

Ниже приведен фрагмент кода, который с помощью API пакетной службы .NET отправляет эффективный запрос пакетной службе для получения статистики по определенному набору пулов. У пользователя пакетной службы есть как тестовые, так и рабочие пулы. Идентификаторы тестовых пулов имеют префикс "test", а рабочих пулов — "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();

Совет

Экземпляр ODATADetailLevel с предложениями Select и Expand также можно передать в соответствующие методы Get, чтобы ограничить объем возвращаемых данных, например в метод PoolOperations.GetPool.

Сопоставление API REST и .NET пакетной службы

Имена и регистр свойств в строках фильтрации, выборки и развертывания должны полностью соответствовать аналогичным элементам в REST API. В таблицах ниже приведено сопоставление элементов API в .NET и REST.

Сопоставления для строк фильтрации

  • Методы списка .NET: каждому из .NET-методов API в этом столбце объект ODATADetailLevel передается в качестве параметра.
  • Запросы списка REST— каждая страница REST API, связанная с этим столбцом, содержит таблицу со свойствами и операциями, разрешенными в строках фильтрации. Вы можете использовать эти имена свойств и операции при создании строки ODATADetailLevel.FilterClause.
Методы списка .NET Запросы списка REST
CertificateOperations.ListCertificates Получение списка сертификатов в учетной записи
CloudTask.ListNodeFiles Получение списка файлов, связанных с задачей
JobOperations.ListJobPreparationAndReleaseTaskStatus Получение состояния подготовки задания и задачи деблокирования задания
JobOperations.ListJobs Получение списка заданий в учетной записи
JobOperations.ListNodeFiles Получение списка файлов в узле
JobOperations.ListTasks Получение списка задач, связанных с заданием
JobScheduleOperations.ListJobSchedules Получение расписаний для заданий в учетной записи
JobScheduleOperations.ListJobs Получение списка заданий, связанных с расписанием задания
PoolOperations.ListComputeNodes Получение списка вычислительных узлов в пуле
PoolOperations.ListPools Получение списка пулов учетной записи

Сопоставления для строк выборки

  • Типы пакетной службы для .NET: типы API пакетной службы для .NET.
  • Сущности REST API: каждая страница в этом столбце содержит одну таблицу или несколько с именами свойств API REST для соответствующих типов. Эти имена свойств используются при создании строк выборки . Они также используются при создании строки ODATADetailLevel.SelectClause.
Типы пакетной службы для .NET Сущности REST API
Сертификат Получение информации о сертификате
CloudJob Получение информации о задании
CloudJobSchedule Получение информации о расписании задания
ComputeNode Получение информации об узле
CloudPool Получение информации о пуле
CloudTask Получение информации о задаче

Пример. Создание строки фильтрации

Чтобы создать строку фильтрации для ODATADetailLevel.FilterClause, найдите соответствующую страницу REST API. Доступные для выбора свойства и их поддерживаемые операторы находятся в первой многострочной таблице. Например, вы хотите получить все задачи с ненулевым кодом возврата. Проверьте "Вывод задач, связанных с заданием", чтобы найти строку с соответствующим свойством и допустимые операторы:

Свойство Разрешенные операции Тип
executionInfo/exitCode eq, ge, gt, le , lt Int

Связанная строка фильтрации:

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

Пример. Создание строки выборки

Чтобы создать ODATADetailLevel.SelectClause, найдите соответствующую страницу REST API для сущности, которую вы перечисляете. Доступные для выбора свойства и их поддерживаемые операторы находятся в первой многострочной таблице. Например, вы хотите получить только идентификатор и командную строку для каждой задачи в списке. Выберите Получение информации о задаче":

Свойство Тип Примечания
id String The ID of the task.
commandLine String The command line of the task.

Связанная строка выборки:

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...

В примере показано как путем ограничения свойств и количества возвращаемых элементов можно значительно уменьшить время отклика на запрос. Этот и другие примеры проектов находятся в репозитории azure-batch-samples на сервисе GitHub.

Библиотека BatchMetrics

Пример проекта BatchMetrics демонстрирует, как эффективно отслеживать ход выполнения задания пакетной службы Azure с помощью API пакетной службы.

Данный пример включает проект библиотеки класса .NET, который можно интегрировать в ваши проекты. Существует также простая программа для командной строки для выполнения упражнений и демонстрации использования библиотеки.

В примере приложения проекта демонстрируются следующие операции:

  • Выбор определенных атрибутов для загрузки только необходимых свойств
  • Фильтрация времени смены состояния для загрузки только изменений, отправленных с момента последнего запроса

Например, в библиотеке BatchMetrics используется приведенный ниже метод. Он возвращает объект ODATADetailLevel, указывающий, что для сущностей, к которым обращен запрос, нужно получить только свойства id и state. Он также указывает, что должны быть возвращены только те сущности, состояние которых изменилось с момента, указанного в значении параметра DateTime .

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

Дальнейшие действия