Создание формулы для автоматизации масштабирования вычислительных узлов в пуле пакетной службы

Пакетная служба Azure может автоматически масштабировать пулы в зависимости от определенных вами параметров, экономии времени и денег. Автоматическое масштабирование позволяет пакетной службе динамически добавлять узлы в пул при росте потребностей задачи, а также удалять вычислительные узлы по мере уменьшения требований задачи.

Чтобы включить автоматическое масштабирование пула вычислительных узлов, вы связываете пул с определенной формулой автомасштабирования. Пакетная служба использует эту формулу автомасштабирования, чтобы определить количество узлов, необходимых для выполнения рабочей нагрузки. Эти узлы могут быть выделенными узлами или точечными узлами Azure. Пакет периодически проверяет данные метрик службы и использует его для настройки количества узлов в пуле на основе формулы и интервала, который вы определяете.

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

Внимание

При создании учетной записи пакетной службы можно указать режим распределения пула, который определяет, выделяются ли пулы в подписке на пакетную службу (по умолчанию) или в вашей пользовательской подписке. Если учетная запись пакетной службы была создана с конфигурацией пакетной службы по умолчанию, то она имеет ограничение на максимальное количество ядер, которые могут использоваться для обработки. Пакетная служба будет создавать вычислительные узлы только до достижения этого предельного количества ядер. По этой причине пакетная служба может не достичь целевого количества вычислительных узлов, указанных формулой автомасштабирования. Сведения о том, как просматривать и увеличивать квоты учетной записи, см. в разделе "Квоты и ограничения" для службы пакетная служба Azure.

Если вы создали свою учетную запись в режиме пользовательской подписки, тогда ваша учетная запись разделит между остальными основную квоту для подписки. Дополнительные сведения см. в разделе Ограничения виртуальных машин в статье Подписка Azure, границы, квоты и ограничения службы.

Примеры формул автомасштабирования

Формула автомасштабирования представляет собой определяемое пользователем строковое значение, которое содержит один или несколько операторов. Формула автоматического масштабирования назначается элементу autoScaleFormula пула (REST для пакетной службы) или свойству CloudPool.AutoScaleFormula (.NET для пакетной службы). С помощью этой формулы пакетная служба определяет целевое количество вычислительных узлов в пуле для следующего интервала обработки. Размер строки формулы не может превышать 8 КБ, а сама строка может содержать до 100 операторов, разделенных точкой с запятой, а также разрывы строк и комментарии.

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

$myNewVariable = function($ServiceDefinedVariable, $myCustomVariable);

Обычно формулы содержат несколько инструкций, выполняющих операции со значениями, полученными в предыдущих инструкциях. Например, сначала вы получите значение для variable1, а затем передайте его в функцию, чтобы заполнить variable2:

$variable1 = function1($ServiceDefinedVariable);
$variable2 = function2($OtherServiceDefinedVariable, $variable1);

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

Целевое число узлов может быть выше, меньше или совпадает с текущим числом узлов этого типа в пуле. Пакетная служба оценивает формулу автомасштабирования пула с определенными интервалами автоматического масштабирования. Затем она изменяет целевое количество узлов каждого типа в пуле на новое значение, полученное по формуле автомасштабирования на момент оценки.

Примеры формул автомасштабирования

В следующих примерах показаны две формулы автомасштабирования, которые можно настроить для работы в большинстве сценариев. Переменные startingNumberOfVMs и maxNumberofVMs в этих формулах можно изменять произвольным образом.

Ожидающие выполнения задачи

Если используется эта формула автоматического масштабирования, пул создается с одной виртуальной машиной. Метрика $PendingTasks обозначает количество задач, находящихся в очереди или в состоянии выполнения. Формула находит среднее число ожидающих выполнения задач за последние 180 секунд и соответствующим образом задает значение переменной $TargetDedicatedNodes. Формула гарантирует, что целевое число выделенных узлов никогда не превысит значение 25. По мере добавления новых задач пул автоматически расширяется. При завершении задач виртуальные машины высвобождаются, и формула автомасштабирования сжимает размер пула.

Эта формула масштабирует выделенные узлы, но ее можно изменить для масштабирования пулов точечных узлов.

startingNumberOfVMs = 1;
maxNumberofVMs = 25;
pendingTaskSamplePercent = $PendingTasks.GetSamplePercent(180 * TimeInterval_Second);
pendingTaskSamples = pendingTaskSamplePercent < 70 ? startingNumberOfVMs : avg($PendingTasks.GetSample(180 * TimeInterval_Second));
$TargetDedicatedNodes=min(maxNumberofVMs, pendingTaskSamples);
$NodeDeallocationOption = taskcompletion;

Внимание

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

Замещенные узлы

В этом примере используется пул, который создается с 25 пулами точечных узлов. Каждый раз, когда точечный узел преумножен, он заменяется выделенным узлом. Как и в первом примере, переменная maxNumberofVMs не позволяет увеличивать пул, добавляя больше 25 виртуальных машин. Этот пример полезен для использования точечных виртуальных машин, а также для обеспечения того, чтобы в течение всего времени существования пула выполнялось только фиксированное число предварительных попыток.

maxNumberofVMs = 25;
$TargetDedicatedNodes = min(maxNumberofVMs, $PreemptedNodeCount.GetSample(180 * TimeInterval_Second));
$TargetLowPriorityNodes = min(maxNumberofVMs , maxNumberofVMs - $TargetDedicatedNodes);
$NodeDeallocationOption = taskcompletion;

Дополнительные сведения о создании формул автомасштабирования см. далее в этой статье.

Переменные

В формуле автоматического масштабирования можно использовать как служебные, так и пользовательские переменные.

Служебные переменные встроены в пакетную службу. Некоторые из них доступны для чтения и записи, а некоторые — только для чтения.

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

Примечание.

Служебные переменные всегда начинаются с символа доллара ($). Для определяемых пользователем переменных знак доллара является необязательным.

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

Определяемые службой переменные для чтения и записи

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

«Переменная» Description
$TargetDedicatedNodes Целевое количество выделенных вычислительных узлов для пула. Указан в качестве целевого объекта, так как пул может не всегда достичь требуемого количества узлов. Например, если целевое число выделенных узлов изменяется с помощью оценки автомасштабирования до достижения начального целевого объекта пула, пул может не достичь целевого объекта.

Пул в учетной записи, созданной в режиме пакетной службы, может не достичь целевого объекта, если целевой объект превышает узел учетной записи пакетной службы или квоту ядра. Пул в учетной записи, созданной в режиме подписки пользователя, может не достичь целевого объекта, если целевой объект превышает квоту общего ядра для подписки.
$TargetLowPriorityNodes Целевое количество выделенных вычислительных узлов для пула. Указан в качестве целевого объекта, так как пул может не всегда достичь требуемого количества узлов. Например, если целевое число точечных узлов изменяется с помощью оценки автомасштабирования до достижения начального целевого объекта пула, пул может не достичь целевого объекта. Пул может также не достичь целевого объекта, если целевой объект превышает узел учетной записи пакетной службы или квоту ядра.

Дополнительные сведения о точечных вычислительных узлах см. в статье Использование точечных виртуальных машин с пакетной службой.
$NodeDeallocationOption Действие, выполняемое после удаления вычислительных узлов из пула. Возможны следующие значения:
- requeue: значение по умолчанию. Немедленно завершает задачи и помещает их обратно в очередь заданий, чтобы они были перепланированы. Это действие гарантирует, что целевое количество узлов будет достигнуто максимально быстро. Однако это может быть менее эффективным, так как все выполняемые задачи прерваны, а затем должны быть перезапущены.
- terminate: немедленное завершение задач с удалением из очереди заданий.
- taskcompletion: ожидание завершения выполнения текущих задач с удалением узла из пула. Этот параметр позволяет избежать прерывания задач и повторного помещения в очередь без сохранения выполненной работы.
- retaineddata: ожидание очистки всех сохраненных в узле данных локальных задач перед удалением узла из пула.

Примечание.

Вместо переменной $TargetDedicatedNodes также можно использовать ее псевдоним $TargetDedicated, а вместо $TargetLowPriorityNodes — псевдоним $TargetLowPriority. Если в формуле заданы полностью именованные переменные и его псевдонимы, то значение, назначенное полностью именованной переменной, имеет приоритет.

Определяемые службой переменные только для чтения

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

Внимание

Задачи выпуска задания в настоящее время не включаются в переменные, предоставляющие количество задач, например $ActiveTasks и $PendingTasks. В зависимости от формулы автомасштабирования это может привести к удалению узлов при отсутствии доступных узлов для выполнения задач выпуска задания.

Совет

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

«Переменная» Description
$CPUPercent Средний объем использования ЦП в процентах.
$WallClockSeconds Затраченное время в секундах. Выход на пенсию после 2024-мар-31.
$MemoryBytes Среднее количество используемых мегабайт. Выход на пенсию после 2024-мар-31.
$DiskBytes Среднее количество гигабайт, используемых на локальных дисках. Выход на пенсию после 2024-мар-31.
$DiskReadBytes Число переданных байтов. Выход на пенсию после 2024-мар-31.
$DiskWriteBytes Количество записанных байт. Выход на пенсию после 2024-мар-31.
$DiskReadOps Количество операций чтения с диска. Выход на пенсию после 2024-мар-31.
$DiskWriteOps Количество операций записи на диск. Выход на пенсию после 2024-мар-31.
$NetworkInBytes Количество входящих байт. Выход на пенсию после 2024-мар-31.
$NetworkOutBytes Количество исходящих байт. Выход на пенсию после 2024-мар-31.
$SampleNodeCount Количество вычислительных узлов. Выход на пенсию после 2024-мар-31.
$ActiveTasks Количество задач, готовых к выполнению, но еще не выполняющихся. Это включает все задачи в активном состоянии, зависимости которых выполнены. Все задачи, которые находятся в активном состоянии, но зависимостей которых не были удовлетворены, исключаются из $ActiveTasks числа. Для задачи с несколькими экземплярами включает количество экземпляров, $ActiveTasks заданных для задачи.
$RunningTasks Количество задач в состоянии выполнения.
$PendingTasks Сумма $ActiveTasks и $RunningTasks.
$SucceededTasks Количество успешно выполненных задач.
$FailedTasks Количество задач, которые не удалось выполнить.
$TaskSlotsPerNode Количество слотов задач, которые могут использоваться для выполнения параллельных задач на одном вычислительном узле в пуле.
$CurrentDedicatedNodes Текущее количество выделенных вычислительных узлов.
$CurrentLowPriorityNodes Текущее количество точечных вычислительных узлов, включая все замещенные узлы.
$UsableNodeCount Количество доступных вычислительных узлов.
$PreemptedNodeCount Количество узлов в пуле, которые находятся в замещенном состоянии.

Предупреждение

Выберите определяемые службой переменные будут сняты после 31 марта 2024 года, как указано в таблице выше. После даты выхода на пенсию эти определяемые службой переменные больше не будут заполнены примерами данных. До этой даты не следует использовать эти переменные.

Примечание.

Используется $RunningTasks при масштабировании на основе количества задач, выполняемых в определенный момент времени, а также $ActiveTasks при масштабировании в зависимости от количества задач, которые были поставлены в очередь на выполнение.

Типы

Формулы автомасштабирования поддерживают следующие типы:

  • двойной точности
  • doubleVec
  • doubleVecList
  • строка
  • метка времени — составная структура, содержащая следующие элементы:
    • year
    • month (1-12)
    • day (1-31)
    • weekday (в формате числа, например 1 — понедельник)
    • hour (час в 24-часовом формате, например 13 соответствует 13:00)
    • minute (00–59)
    • second (00–59)
  • timeinterval
    • TimeInterval_Zero
    • TimeInterval_100ns
    • TimeInterval_Microsecond
    • TimeInterval_Millisecond
    • TimeInterval_Second
    • TimeInterval_Minute
    • TimeInterval_Hour
    • TimeInterval_Day
    • TimeInterval_Week
    • TimeInterval_Year

Операции

Для перечисленных в предыдущем разделе типов разрешены перечисленные ниже операции.

Операция Поддерживаемые операторы Тип результата
double оператор double +, -, *, / двойной точности
double оператор timeinterval * timeInterval
doubleVec оператор double +, -, *, / doubleVec
doubleVec оператор doubleVec +, -, *, / doubleVec
timeinterval оператор double *, / timeInterval
timeinterval оператор timeinterval +, - timeInterval
timeinterval оператор timestamp + TIMESTAMP
timestamp оператор timeinterval + TIMESTAMP
timestamp оператор timestamp - timeInterval
оператор double -, ! двойной точности
оператор timeinterval - timeInterval
double оператор double <, <=, ==, =, =, >>! = двойной точности
string оператор string <, <=, ==, =, =, >>! = двойной точности
timestamp оператор timestamp <, <=, ==, =, =, >>! = двойной точности
timeinterval оператор timeinterval <, <=, ==, =, =, >>! = двойной точности
double оператор double &&, || двойной точности

Тестирование двойника с помощью тернарного оператора (double ? statement1 : statement2), приводит к ненулевому значению true и нулю как false.

Функции

Эти предопределенные функции можно использовать при определении формулы автомасштабирования.

Function Возвращаемый тип Description
avg(doubleVecList) двойной точности Среднее значение для всех значений в doubleVecList.
ceil(double) двойной точности Возвращает наименьшее целое значение не меньше двойного.
ceil(doubleVecList) doubleVec Возвращает компонент,мудреный ceil для doubleVecList.
floor(double) двойной точности Возвращает наибольшее целое значение, не превышающее двойное.
floor(doubleVecList) doubleVec Возвращает компонент,мудреный floor для doubleVecList.
len(doubleVecList) двойной точности Возвращает длину вектора, созданного из doubleVecList.
lg(double) двойной точности Возвращает логарифм double по основанию 2.
lg(doubleVecList) doubleVec Возвращает компонент,мудреный lg для doubleVecList.
ln(double) двойной точности Возвращает натуральный логарифм double.
ln(doubleVecList) doubleVec Возвращает компонент,мудреный ln для doubleVecList.
log(double) двойной точности Возвращает логарифм double по основанию 10.
log(doubleVecList) doubleVec Возвращает компонент,мудреный log для doubleVecList.
max(doubleVecList) двойной точности Возвращает максимальное значение в doubleVecList.
min(doubleVecList) двойной точности Возвращает минимальное значение в doubleVecList.
norm(doubleVecList) двойной точности Возвращает 2-норму вектора, созданного из doubleVecList.
percentile(doubleVec v, double p) двойной точности Возвращает элемент процентиля вектора v.
rand() двойной точности Возвращает случайное значение от 0,0 до 1,0.
range(doubleVecList) двойной точности Возвращает разницу между минимальным и максимальным значениями в doubleVecList.
round(double) двойной точности Возвращает ближайшее целое значение в двойном (в формате с плавающей запятой), округляя полпути от нуля.
round(doubleVecList) doubleVec Возвращает компонент,мудреный round для doubleVecList.
std(doubleVecList) двойной точности Возвращает среднеквадратичное отклонение выборки для значений в doubleVecList.
stop() Останавливает вычисление выражения автоматического масштабирования.
sum(doubleVecList) двойной точности Возвращает сумму всех компонентов doubleVecList.
time(string dateTime="") TIMESTAMP Возвращает метку времени для текущего времени, если параметр не передан, и метку времени для строки dateTime, если параметр передан. Поддерживаемые форматы даты и времени: W3C-DTF и RFC 1123.
val(doubleVec v, double i) двойной точности Возвращает значение элемента с индексом i в векторе v с начальным индексом 0.

Некоторые функции, описанные в предыдущей таблице, могут принимать список в качестве аргумента. Список значений, разделенных запятыми, — это любая комбинация типов double и doubleVec. Например:

doubleVecList := ( (double | doubleVec)+(, (double | doubleVec) )* )?

Значение doubleVecList перед оценкой преобразуется в одно значение doubleVec. Например, если v = [1,2,3], то вызов avg(v) эквивалентен вызову avg(1,2,3). Вызов avg(v, 7) эквивалентен вызову avg(1,2,3,7).

Метрики

При определении формулы можно использовать как метрики ресурсов, так и задач. Целевое количество выделенных узлов в пуле определяется на основе данных метрики, которые были получены и оценены. Дополнительные сведения о каждой метрии см. в разделе "Переменные ".

Метрическая Description
Ресурс Метрики ресурсов основаны на использовании ресурсов ЦП, памяти и пропускной способности вычислительных узлов, а также количестве узлов.

Для внесения изменений с учетом количества узлов используются следующие служебные переменные:
- $TargetDedicatedNodes
- $TargetLowPriorityNodes
- $CurrentDedicatedNodes
- $CurrentLowPriorityNodes
- $PreemptedNodeCount
- $UsableNodeCount

Эти определяемые службой переменные полезны для корректировки на основе использования ресурсов узла:
- $CPUPercent
- $WallClockSeconds
- $MemoryBytes
- $DiskBytes
- $DiskReadBytes
- $DiskWriteBytes
- $DiskReadOps
- $DiskWriteOps
- $NetworkInBytes
- $NetworkOutBytes
Задача Метрики задач основаны на состоянии задач (активные, ожидающие и завершенные). Следующие определяемые службой переменные полезны для корректировки размера пула на основе метрик задач:
- $ActiveTasks
- $RunningTasks
- $PendingTasks
- $SucceededTasks
- $FailedTasks

Получение выборки данных

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

Методы

Формулы автомасштабирования обрабатывают выборки данных метрик, предоставляемых пакетной службой. Формула увеличивает или сжимает вычислительные узлы пула на основе получаемых значений. Определяемые службой переменные — это объекты, предоставляющие методы для доступа к данным, связанным с этим объектом. Например, следующее выражение иллюстрирует запрос для получения данных об использовании ЦП за последние пять минут.

$CPUPercent.GetSample(TimeInterval_Minute * 5)

Следующие методы можно использовать для получения примеров данных о определяемых службой переменных.

Метод Description
GetSample() Метод GetSample() возвращает вектор выборок данных.

Выборка — это данные метрики за 30 секунд. Другими словами, выборки делаются каждые 30 секунд. Но, как отмечалось ниже, существует задержка между сбором образца и когда она доступна для формулы. Таким образом, не все примеры для заданного периода времени могут быть доступны для оценки формулой.

- doubleVec GetSample(double count): указывает нужное количество выборок из числа самых свежих. GetSample(1) возвращает последнюю доступную выборку. Этот метод GetSample(1) не следует использовать для таких метрик, как $CPUPercent, так как нет возможности узнать, когда была получена эта выборка. Она может оказаться свежей, но может и устареть, если в системе возникли проблемы. В таких случаях лучше использовать интервалы, как показано ниже.

- doubleVec GetSample((timestamp or timeinterval) startTime [, double samplePercent]): задает интервал времени для получения данных выборки. Также можно указать долю выборок, которые должны быть доступны в течение запрошенного интервала времени. Например, $CPUPercent.GetSample(TimeInterval_Minute * 10) вернет 20 выборок, если в журнале CPUPercent присутствуют все выборки за последние 10 минут. Если данные за последнюю минуту недоступны, этот метод вернет только 18 выборок. В этом случае $CPUPercent.GetSample(TimeInterval_Minute * 10, 95) произойдет сбой из-за того, что доступны только 90 процентов выборок, но $CPUPercent.GetSample(TimeInterval_Minute * 10, 80) будут успешными.

- doubleVec GetSample((timestamp or timeinterval) startTime, (timestamp or timeinterval) endTime [, double samplePercent]): задает интервал времени для получения данных, т. е. начало и конец получения. Как упоминание выше, существует задержка между сбором выборки и когда она становится доступной для формулы. Эту задержку следует учитывать при использовании метода GetSample. Ознакомьтесь с GetSamplePercent ниже.
GetSamplePeriod() Возвращает период выборок, которые были получены в историческом наборе данных выборок.
Count() Возвращает общее количество примеров в журнале метрик.
HistoryBeginTime() Возвращает метку времени самой старой доступной выборки данных метрики.
GetSamplePercent() Возвращает процент выборок, которые доступны для заданного интервала времени. Например, doubleVec GetSamplePercent( (timestamp or timeinterval) startTime [, (timestamp or timeinterval) endTime] ). Так как метод GetSample завершается сбоем, то если процент возвращаемых выборок меньше указанного в параметре samplePercent, можно сначала воспользоваться методом GetSamplePercent для проверки. Затем при недостаточном количестве выборок можно выполнить другое действие без прерывания оценки автоматического масштабирования.

Примеры

Пакетная служба периодически принимает выборки метрик задач и ресурсов, делая их доступными для формул автомасштабирования. Эти выборки записываются пакетной службой каждые 30 секунд. Однако обычно возникает задержка между записью этих выборок и тем, когда они доступны (и считываются) формул автомасштабирования. Кроме того, примеры могут не записываться для определенного интервала из-за таких факторов, как сеть или другие проблемы инфраструктуры.

Процент выборок

При samplePercent передаче GetSample() методу или GetSamplePercent() методу процент ссылается на сравнение общего количества выборок, записанных службой пакетной службы, и количества выборок, доступных формуле автомасштабирования.

Рассмотрим 10-минутный интервал времени в качестве примера. Так как выборки записываются каждые 30 секунд в течение этого 10-минутного интервала времени, максимальное общее количество выборок, записанных пакетом, составляет 20 выборок (2 в минуту). Однако из-за внутренней задержки механизма отчетности и других проблем в Azure может быть только 15 примеров, доступных в формуле автомасштабирования для чтения. Таким образом, например, для этого 10-минутного периода может быть доступно только 75 процентов от общего количества записанных примеров.

Метод GetSample() и диапазоны выборок

Формулы автомасштабирования растут и сжимают пулы, добавляя или удаляя узлы. Так как узлы стоят вам денег, убедитесь, что формулы используют интеллектуальный метод анализа, основанный на достаточных данных. Рекомендуется использовать анализ типа трендов в формулах. С таким анализом пулы увеличиваются и уменьшаются на основе диапазона собранных выборок.

С этой целью используйте метод GetSample(interval look-back start, interval look-back end) для возврата вектора выборок.

$runningTasksSample = $RunningTasks.GetSample(1 * TimeInterval_Minute, 6 * TimeInterval_Minute);

При вычислении приведенной выше строки пакетная служба возвращает диапазон выборок в виде вектора значений. Например:

$runningTasksSample=[1,1,1,1,1,1,1,1,1,1];

После сбора вектора примеров можно использовать такие функции, как min(), max()и avg() для получения значимых значений из собранного диапазона.

Чтобы выполнить дополнительную осторожность, вы можете принудительно выполнить оценку формул, если для определенного периода времени доступно меньше определенного процента выборки. При принудительном сбое вычисления формулы вы указываете пакету прекратить дальнейшую оценку формулы, если указанный процент выборок недоступен. Размер пула при этом изменяться не будет. Чтобы указать необходимый процент выборок для успешного вычисления, укажите его как третий параметр в методе GetSample(). Здесь указано, что обязательный процент выборок равен 75 %:

$runningTasksSample = $RunningTasks.GetSample(60 * TimeInterval_Second, 120 * TimeInterval_Second, 75);

Так как в образце доступности может возникнуть задержка, всегда следует указать диапазон времени с временем начала поиска, которое старше одной минуты. Для распространения выборок через систему занимает около одной минуты, поэтому выборки в диапазоне (0 * TimeInterval_Second, 60 * TimeInterval_Second) могут быть недоступны. Опять же, можно использовать параметр процента GetSample() для принудительного требования определенного процента выборок.

Внимание

Настоятельно рекомендуется избегать использования толькоGetSample(1) в формулах автомасштабирования. Это связано с тем, что, по GetSample(1) сути, говорит пакетной службе: "Дайте мне последний пример, который вы получили, независимо от того, как давно вы получили его". Так как это только один пример, и это может быть более старый пример, он может не представлять собой более широкую картину недавней задачи или состояния ресурсов. Если метод GetSample(1)все же используется, убедитесь, что он является частью большей инструкции, а не единственной точкой данных, от которой зависит ваша формула.

Написание формулы автомасштабирования

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

Сначала определим требования к новой формуле автомасштабирования. Формула должна выполнять следующее:

  • Увеличивать целевое количество выделенных вычислительных узлов в пуле при высокой загрузке ЦП.
  • Уменьшать целевое количество выделенных вычислительных узлов в пуле при низкой загрузке ЦП.
  • Всегда ограничивать максимальное количество выделенных узлов на уровне 400.
  • При уменьшении количества узлов не удаляйте узлы, на которых выполняются задачи. Если нужно удалить узлы, дождитесь выполнения задач на них.

Первая инструкция в формуле увеличивает количество узлов во время высокой загрузки ЦП. Вы определяете инструкцию, заполняющую определяемую пользователем переменную ($totalDedicatedNodes) значением, равным 110 процентам текущего целевого числа выделенных узлов, но только если минимальное среднее использование ЦП за последние 10 минут превышает 70 процентов. В противном случае используйте значение текущего количества выделенных узлов.

$totalDedicatedNodes =
    (min($CPUPercent.GetSample(TimeInterval_Minute * 10)) > 0.7) ?
    ($CurrentDedicatedNodes * 1.1) : $CurrentDedicatedNodes;

Чтобы уменьшить количество выделенных узлов при низком использовании ЦП, следующая инструкция в формуле задает ту же $totalDedicatedNodes переменную до 90 процентов текущего целевого числа выделенных узлов, если среднее использование ЦП за последние 60 минут составило менее 20 процентов. В противном случае используется текущее значение, заполненное $totalDedicatedNodes в приведенной выше инструкции.

$totalDedicatedNodes =
    (avg($CPUPercent.GetSample(TimeInterval_Minute * 60)) < 0.2) ?
    ($CurrentDedicatedNodes * 0.9) : $totalDedicatedNodes;

Теперь ограничьте целевое число выделенных вычислительных узлов не более 400.

$TargetDedicatedNodes = min(400, $totalDedicatedNodes);

Наконец, убедитесь, что узлы не удаляются до завершения их задач.

$NodeDeallocationOption = taskcompletion;

Вот полная формула:

$totalDedicatedNodes =
    (min($CPUPercent.GetSample(TimeInterval_Minute * 10)) > 0.7) ?
    ($CurrentDedicatedNodes * 1.1) : $CurrentDedicatedNodes;
$totalDedicatedNodes =
    (avg($CPUPercent.GetSample(TimeInterval_Minute * 60)) < 0.2) ?
    ($CurrentDedicatedNodes * 0.9) : $totalDedicatedNodes;
$TargetDedicatedNodes = min(400, $totalDedicatedNodes);
$NodeDeallocationOption = taskcompletion;

Примечание.

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

Интервал автоматического масштабирования

По умолчанию пакетная служба изменяет размер пула по указанной формуле автомасштабирования каждые 15 минут. Этот интервал можно настроить с помощью следующих свойств пула:

Минимальный интервал составляет пять минут, а максимальный — 168 часов. Если указан интервал за пределами этого диапазона, пакетная служба возвращает ошибку "Неправильный запрос (400)".

Примечание.

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

Создание пула с поддержкой автомасштабирования с помощью пакетов SDK пакетной службы

Пул автомасштабирования можно настроить с помощью любых пакетов SDK пакетной службы, REST API пакетной службы, командлетов пакетной службы PowerShell или интерфейса командной строки пакетной службы. В этом разделе представлены примеры для .NET и Python.

.NET

Чтобы создать пул с поддержкой автомасштабирования в .NET, выполните указанные ниже действия.

  1. Создайте пул с помощью метода BatchClient.PoolOperations.CreatePool.
  2. Задайте для свойства CloudPool.AutoScaleEnabled значение true.
  3. Задайте свойство CloudPool.AutoScaleFormula с помощью формулы автомасштабирования.
  4. (Необязательно.) Задайте свойство CloudPool.AutoScaleEvaluationInterval (значение по умолчанию — 15 минут).
  5. Зафиксируйте пул с помощью метода CloudPool.Commit или CommitAsync.

В следующем примере создается пул с поддержкой автомасштабирования в .NET. Формула автомасштабирования пула устанавливает целевое количество выделенных узлов равным 5 по понедельникам и 1 в остальные дни недели. Интервал автомасштабирования составляет 30 минут. В этом и других фрагментах кода C#, приведенных в этой статье, myBatchClient представляет собой правильно инициализированный экземпляр класса BatchClient.

CloudPool pool = myBatchClient.PoolOperations.CreatePool(
                    poolId: "mypool",
                    virtualMachineSize: "standard_d1_v2",
                    VirtualMachineConfiguration: new VirtualMachineConfiguration(
                        imageReference: new ImageReference(
                                            publisher: "MicrosoftWindowsServer",
                                            offer: "WindowsServer",
                                            sku: "2019-datacenter-core",
                                            version: "latest"),
                        nodeAgentSkuId: "batch.node.windows amd64");
pool.AutoScaleEnabled = true;
pool.AutoScaleFormula = "$TargetDedicatedNodes = (time().weekday == 1 ? 5:1);";
pool.AutoScaleEvaluationInterval = TimeSpan.FromMinutes(30);
await pool.CommitAsync();

Внимание

При создании пула с поддержкой автомасштабирования не указывайте параметр targetDedicatedNodes или параметр targetLowPriorityNodes в вызовеCreatePool. Вместо этого укажите AutoScaleEnabled свойства AutoScaleFormula в пуле. Значения этих свойств определяют целевое количество каждого типа узлов.

Чтобы вручную изменить размер пула с включенным автомасштабированием (например, с помощью BatchClient.PoolOperations.ResizePoolAsync), сначала отключите автомасштабирование пула, а затем измените его размер.

Совет

Дополнительные примеры использования пакета SDK для .NET см . в репозитории быстрого запуска пакетной службы .NET на GitHub.

Python

Чтобы создать пул с поддержкой автомасштабирования с помощью пакета SDK для Python:

  1. Создайте пул и укажите его конфигурацию.
  2. Добавьте пул в клиент службы.
  3. Включите автомасштабирование для пула с использованием созданной вами формулы.

В следующем примере это показано.

# Create a pool; specify configuration
new_pool = batch.models.PoolAddParameter(
    id="autoscale-enabled-pool",
    virtual_machine_configuration=batchmodels.VirtualMachineConfiguration(
        image_reference=batchmodels.ImageReference(
          publisher="Canonical",
          offer="UbuntuServer",
          sku="20.04-LTS",
          version="latest"
            ),
        node_agent_sku_id="batch.node.ubuntu 20.04"),
    vm_size="STANDARD_D1_v2",
    target_dedicated_nodes=0,
    target_low_priority_nodes=0
)
batch_service_client.pool.add(new_pool) # Add the pool to the service client

formula = """$curTime = time();
             $workHours = $curTime.hour >= 8 && $curTime.hour < 18;
             $isWeekday = $curTime.weekday >= 1 && $curTime.weekday <= 5;
             $isWorkingWeekdayHour = $workHours && $isWeekday;
             $TargetDedicated = $isWorkingWeekdayHour ? 20:10;""";

# Enable autoscale; specify the formula
response = batch_service_client.pool.enable_auto_scale(pool_id, auto_scale_formula=formula,
                                            auto_scale_evaluation_interval=datetime.timedelta(minutes=10),
                                            pool_enable_auto_scale_options=None,
                                            custom_headers=None, raw=False)

Совет

Дополнительные примеры использования пакета SDK для Python см . в репозитории быстрого запуска пакетной службы Python на сайте GitHub.

Включение автомасштабирования в имеющемся пуле

Каждый пакет SDK пакетной службы предоставляет способ включения автомасштабирования. Например:

При включении автомасштабирования в имеющемся пуле учитывайте указанные ниже условия.

  • Если автомасштабирование в пуле отключено, при выполнении запроса необходимо указать допустимую формулу автомасштабирования. При необходимости можно указать интервал автомасштабирования. Если интервал не указан, используется значение по умолчанию, равное 15 минутам.
  • Если в пуле включено автомасштабирование, можно указать новую формулу, новый интервал или и то, и другое. Необходимо указать по крайней мере одно из этих свойств.
    • При указании нового интервала автомасштабирования существующее расписание останавливается и запускается новое расписание. Время начала нового расписания — это время подачи запроса на включение автомасштабирования.
    • Если опустить формулу автомасштабирования или интервал, служба пакетной службы продолжает использовать текущее значение этого параметра.

Примечание.

Если вы указали значения для параметров CreatePool targetDedicatedNodes или targetLowPriorityNodes метода при создании пула в .NET или для сопоставимых параметров на другом языке, эти значения игнорируются при вычислении формулы автомасштабирования.

В этом примере C# для включения автомасштабирования в существующем пуле используется библиотека .NET пакетной службы.

// Define the autoscaling formula. This formula sets the target number of nodes
// to 5 on Mondays, and 1 on every other day of the week
string myAutoScaleFormula = "$TargetDedicatedNodes = (time().weekday == 1 ? 5:1);";

// Set the autoscale formula on the existing pool
await myBatchClient.PoolOperations.EnableAutoScaleAsync(
    "myexistingpool",
    autoscaleFormula: myAutoScaleFormula);

Обновление формулы автомасштабирования

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

await myBatchClient.PoolOperations.EnableAutoScaleAsync(
    "myexistingpool",
    autoscaleFormula: myNewFormula);

Обновление интервала автомасштабирования

Чтобы обновить интервал оценки автомасштабирования для существующего пула с поддержкой автомасштабирования, вызовите операцию для включения автомасштабирования еще раз с новым интервалом. Например, чтобы задать для интервала оценки автомасштабирования значение 60 минут в пуле с уже включенным автомасштабированием, необходимо сделать следующее:

await myBatchClient.PoolOperations.EnableAutoScaleAsync(
    "myexistingpool",
    autoscaleEvaluationInterval: TimeSpan.FromMinutes(60));

Оценка формулы автомасштабирования

Прежде чем применить формулу к пулу, ее можно оценить. Это позволяет протестировать результаты формулы до их помещения в рабочую среду.

Прежде чем оценить формулу автомасштабирования, необходимо включить автомасштабирование в пуле с допустимой формулой, например с помощью однострочной формулы $TargetDedicatedNodes = 0. Затем для оценки формулы, которую требуется протестировать, выполните одно из следующих действий:

  • Вызовите метод BatchClient.PoolOperations.EvaluateAutoScale или EvaluateAutoScaleAsync.

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

  • Оцените формулу автомасштабирования.

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

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

// First obtain a reference to an existing pool
CloudPool pool = await batchClient.PoolOperations.GetPoolAsync("myExistingPool");

// If autoscaling isn't already enabled on the pool, enable it.
// You can't evaluate an autoscale formula on a non-autoscale-enabled pool.
if (pool.AutoScaleEnabled == false)
{
    // You need a valid autoscale formula to enable autoscaling on the
    // pool. This formula is valid, but won't resize the pool:
    await pool.EnableAutoScaleAsync(
        autoscaleFormula: "$TargetDedicatedNodes = $CurrentDedicatedNodes;",
        autoscaleEvaluationInterval: TimeSpan.FromMinutes(5));

    // Batch limits EnableAutoScaleAsync calls to once every 30 seconds.
    // Because you want to apply our new autoscale formula below if it
    // evaluates successfully, and you *just* enabled autoscaling on
    // this pool, pause here to ensure you pass that threshold.
    Thread.Sleep(TimeSpan.FromSeconds(31));

    // Refresh the properties of the pool so that we've got the
    // latest value for AutoScaleEnabled
    await pool.RefreshAsync();
}

// You must ensure that autoscaling is enabled on the pool prior to
// evaluating a formula
if (pool.AutoScaleEnabled == true)
{
    // The formula to evaluate - adjusts target number of nodes based on
    // day of week and time of day
    string myFormula = @"
        $curTime = time();
        $workHours = $curTime.hour >= 8 && $curTime.hour < 18;
        $isWeekday = $curTime.weekday >= 1 && $curTime.weekday <= 5;
        $isWorkingWeekdayHour = $workHours && $isWeekday;
        $TargetDedicatedNodes = $isWorkingWeekdayHour ? 20:10;
    ";

    // Perform the autoscale formula evaluation. Note that this code does not
    // actually apply the formula to the pool.
    AutoScaleRun eval =
        await batchClient.PoolOperations.EvaluateAutoScaleAsync(pool.Id, myFormula);

    if (eval.Error == null)
    {
        // Evaluation success - print the results of the AutoScaleRun.
        // This will display the values of each variable as evaluated by the
        // autoscale formula.
        Console.WriteLine("AutoScaleRun.Results: " +
            eval.Results.Replace("$", "\n    $"));

        // Apply the formula to the pool since it evaluated successfully
        await batchClient.PoolOperations.EnableAutoScaleAsync(pool.Id, myFormula);
    }
    else
    {
        // Evaluation failed, output the message associated with the error
        Console.WriteLine("AutoScaleRun.Error.Message: " +
            eval.Error.Message);
    }
}

В случае успешного вычисления формулы, показанной в этом фрагменте, будет получен результат, подобный следующему:

AutoScaleRun.Results:
    $TargetDedicatedNodes=10;
    $NodeDeallocationOption=requeue;
    $curTime=2016-10-13T19:18:47.805Z;
    $isWeekday=1;
    $isWorkingWeekdayHour=0;
    $workHours=0

Получение сведений о выполнениях автомасштабирования

Рекомендуется периодически проверка оценки пакетной службы формулы автомасштабирования. Чтобы сделать это, получите (или обновите) ссылку на пул и проверьте свойства последнего выполнения автомасштабирования в этом пуле.

В .NET пакетной службы свойство CloudPool.AutoScaleRun обладает несколькими свойствами, которые предоставляют сведения о последнем выполнении автомасштабирования в пуле.

В REST API запрос Получение сведений о пуле возвращает сведения о пуле, в том числе результаты последнего выполнения автомасштабирования, в свойстве autoScaleRun.

В следующем примере C# для вывода сведений о последнем выполнении автомасштабирования в пуле myPool используется библиотека .NET пакетной службы.

await Cloud pool = myBatchClient.PoolOperations.GetPoolAsync("myPool");
Console.WriteLine("Last execution: " + pool.AutoScaleRun.Timestamp);
Console.WriteLine("Result:" + pool.AutoScaleRun.Results.Replace("$", "\n  $"));
Console.WriteLine("Error: " + pool.AutoScaleRun.Error);

Выходные данные выборки из предыдущего примера:

Last execution: 10/14/2016 18:36:43
Result:
  $TargetDedicatedNodes=10;
  $NodeDeallocationOption=requeue;
  $curTime=2016-10-14T18:36:43.282Z;
  $isWeekday=1;
  $isWorkingWeekdayHour=0;
  $workHours=0
Error:

Получение журнала выполнения автомасштабирования с помощью событий автомасштабирования пула

Проверьте журнал автомасштабирования, выполнив запрос к PoolAutoScaleEvent. Пакет выдает это событие для записи каждого вхождения вычисления и выполнения формул автомасштабирования, что может быть полезно для устранения потенциальных проблем.

Событие выборки для PoolAutoScaleEvent:

{
    "id": "poolId",
    "timestamp": "2020-09-21T23:41:36.750Z",
    "formula": "...",
    "results": "$TargetDedicatedNodes=10;$NodeDeallocationOption=requeue;$curTime=2016-10-14T18:36:43.282Z;$isWeekday=1;$isWorkingWeekdayHour=0;$workHours=0",
    "error": {
        "code": "",
        "message": "",
        "values": []
    }
}

Примеры формул автомасштабирования

Давайте рассмотрим некоторые формулы, которые демонстрируют различные способы настройки количества вычислительных ресурсов в пуле.

Пример 1. Изменение с учетом времени

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

Формула сначала получает значение текущего времени. В рабочие дни (1–5) и часы (8:00–18:00) целевой размер пула равен 20 узлам. В противном случае он равен 10 узлам.

$curTime = time();
$workHours = $curTime.hour >= 8 && $curTime.hour < 18;
$isWeekday = $curTime.weekday >= 1 && $curTime.weekday <= 5;
$isWorkingWeekdayHour = $workHours && $isWeekday;
$TargetDedicatedNodes = $isWorkingWeekdayHour ? 20:10;
$NodeDeallocationOption = taskcompletion;

Для $curTime можно настроить время местного часового пояса, добавив time() к произведению значения TimeZoneInterval_Hour и смещения от UTC. Например, для часового пояса "Горное время США (лето)" укажите значение $curTime = time() + (-6 * TimeInterval_Hour);. Помните, что смещение должно быть скорректировано в начале и конце летнего времени, если применимо.

Пример 2. Изменение с учетом задачи

В этом примере C# размер пула настраивается в зависимости от количества задач в очереди. Комментарии и разрывы строк включаются в строки формул.

// Get pending tasks for the past 15 minutes.
$samples = $PendingTasks.GetSamplePercent(TimeInterval_Minute * 15);
// If you have fewer than 70 percent data points, use the last sample point,
// otherwise use the maximum of last sample point and the history average.
$tasks = $samples < 70 ? max(0,$PendingTasks.GetSample(1)) : max( $PendingTasks.GetSample(1), avg($PendingTasks.GetSample(TimeInterval_Minute * 15)));
// If number of pending tasks is not 0, set targetVM to pending tasks, otherwise
// half of current dedicated.
$targetVMs = $tasks > 0? $tasks:max(0, $TargetDedicatedNodes/2);
// The pool size is capped at 20, if target VM value is more than that, set it
// to 20. This value should be adjusted according to your use case.
$TargetDedicatedNodes = max(0, min($targetVMs, 20));
// Set node deallocation mode - let running tasks finish before removing a node
$NodeDeallocationOption = taskcompletion;

Пример 3. Параллельные задачи

В этом примере кода на C# размер пула изменяется в зависимости от количества задач. Эта формула также учитывает значение TaskSlotsPerNode , заданное для пула. Такой подход полезен, если в пуле поддерживается параллельное выполнение задач.

// Determine whether 70 percent of the samples have been recorded in the past
// 15 minutes; if not, use last sample
$samples = $ActiveTasks.GetSamplePercent(TimeInterval_Minute * 15);
$tasks = $samples < 70 ? max(0,$ActiveTasks.GetSample(1)) : max( $ActiveTasks.GetSample(1),avg($ActiveTasks.GetSample(TimeInterval_Minute * 15)));
// Set the number of nodes to add to one-fourth the number of active tasks
// (the TaskSlotsPerNode property on this pool is set to 4, adjust
// this number for your use case)
$cores = $TargetDedicatedNodes * 4;
$extraVMs = (($tasks - $cores) + 3) / 4;
$targetVMs = ($TargetDedicatedNodes + $extraVMs);
// Attempt to grow the number of compute nodes to match the number of active
// tasks, with a maximum of 3
$TargetDedicatedNodes = max(0,min($targetVMs,3));
// Keep the nodes active until the tasks finish
$NodeDeallocationOption = taskcompletion;

Пример 4. Настройка исходного размера пула

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

В частности, в данной формуле выполняются следующие действия.

  • Она задает исходный размер пула в 4 узла.
  • Не настраивает размер пула в течение первых 10 минут жизненного цикла пула.
  • После первых 10 минут она получает максимальное количество запущенных и активных задач за последние 60 минут.
    • Если оба значения равны 0, указывая, что за последние 60 минут задачи не выполнялись или активны, размер пула имеет значение 0.
    • Если любое из значений больше нуля, изменений не производится.
string now = DateTime.UtcNow.ToString("r");
string formula = string.Format(@"
    $TargetDedicatedNodes = {1};
    lifespan         = time() - time(""{0}"");
    span             = TimeInterval_Minute * 60;
    startup          = TimeInterval_Minute * 10;
    ratio            = 50;

    $TargetDedicatedNodes = (lifespan > startup ? (max($RunningTasks.GetSample(span, ratio), $ActiveTasks.GetSample(span, ratio)) == 0 ? 0 : $TargetDedicatedNodes) : {1});
    ", now, 4);

Следующие шаги