Criar uma fórmula para dimensionar automaticamente os nós de computação em um pool do Lote do Azure

O Lote do Azure pode escalar automaticamente os pools baseado nos parâmetros que você definir, economizando tempo e dinheiro. Com o dimensionamento automático, o Lote adiciona dinamicamente nós a um pool à medida que as demandas de tarefas aumentam e remove os nós de computação à medida que elas que diminuem.

Para habilitar o dimensionamento automático em um pool de nós de computação, você associa o pool a uma fórmula de dimensionamento automático definida por você. O serviço de Lote usa a fórmula de dimensionamento automático para determinar quantos nós de computação são necessários para executar a carga de trabalho. Esses nós podem ser nós dedicados ou nós do Azure Spot. O Lote revisa periodicamente os dados de métricas de serviço e os usa para ajustar o número de nós no pool com base na fórmula e em um intervalo definido por você.

Você pode habilitar o dimensionamento automático ao criar um pool ou aplicá-lo a um pool existente. O Lote permite avaliar suas fórmulas antes de atribuí-las a pools e monitorar o status das execuções de escala automática. Depois de configurar um pool com o dimensionamento automático, você poderá fazer alterações na fórmula mais tarde.

Importante

Ao criar uma conta do Lote, será possível especificar o modo de alocação do pool, que determinará se os pools serão alocados em uma assinatura do serviço de Lote (o padrão) ou na sua assinatura de usuário. Se a conta do Lote foi criada com a configuração de serviço de Lote padrão, essa conta será limitada a um número máximo de núcleos que poderá ser utilizado para processamento. As escalas de serviço de Lote calculam os nós apenas até esse limite de núcleos. Por esse motivo, o serviço do Lote pode não atingir o número alvo de nós de computação especificado por uma fórmula de dimensionamento automático. Para saber como exibir e aumentar suas cotas de conta, confira Cotas e limites para o serviço do Lote do Azure.

Se a conta foi criada com o modo de assinatura de usuário, essa conta irá compartilhar a cota de núcleos para a assinatura. Para saber mais, confiraLimites das Máquinas Virtuais e Assinatura e limites de serviço, cotas e restrições do Azure.

Fórmulas de dimensionamento automático

Uma fórmula de dimensionamento automático é um valor de cadeia de caracteres que você define e que contém uma ou mais instruções. A fórmula de dimensionamento automático é atribuída ao elemento autoScaleFormula de um pool (Lote REST) ou à propriedade CloudPool.AutoScaleFormula (Lote .NET). O serviço do Lote usa sua fórmula para determinar o número de destino dos nós de computação no pool para o próximo intervalo de processamento. A cadeia de caracteres da fórmula não pode exceder 8 KB, pode incluir até 100 instruções separadas por ponto e vírgula e pode incluir quebras de linha e comentários.

Você pode pensar nas fórmulas de escala como uma "linguagem" de dimensionamento automático do Lote. As Instruções da fórmula são expressões de forma livre que podem incluir tanto variáveis definidas pelo serviço, que são definidas pelo serviço do Lote, quanto variáveis definidas pelo usuário. As fórmulas podem executar várias operações com esses valores usando tipos, operadores e funções internas. Por exemplo, uma instrução pode ter a seguinte forma:

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

Geralmente, as fórmulas contêm várias instruções que executam operações nos valores que são obtidos nas instruções anteriores. Por exemplo, primeiro você obtém um valor de variable1 e, em seguida, passa-o para uma função para preencher variable2:

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

Inclua essas instruções na sua fórmula de autoescala para chegar a um número de nós de computação de destino. Os nós dedicados e nós spot têm suas próprias configurações de destino. Uma fórmula de dimensionamento automático pode incluir um valor para nós dedicados de destino, um valor para nós spot de destino ou ambos.

O número alvo de nós pode ser maior, menor ou igual ao número atual de nós desse tipo no pool. O Lote avalia a fórmula de dimensionamento automático de um pool em intervalos de escala automática específicos. O Lote ajusta o número de destino de cada tipo de nó no pool para o número que sua fórmula de autoescala especifica no momento da avaliação.

Exemplos de fórmulas de dimensionamento automático

Os exemplos a seguir mostram duas fórmulas de dimensionamento automático, que podem ser ajustadas para funcionar na maioria dos cenários. É possível ajustar as variáveis startingNumberOfVMs e maxNumberofVMs nos exemplos de fórmulas de acordo com suas necessidades.

Tarefas pendentes

Com esta fórmula de dimensionamento automático, o pool é criado inicialmente com uma única VM. A métrica $PendingTasks define o número de tarefas que estão executando ou na fila. A fórmula localiza o número médio de tarefas pendentes nos últimos 180 segundos e define a variável $TargetDedicatedNodes em conformidade. A fórmula garante que o número de nós dedicados de destino jamais exceda 25 VMs. Conforme novas tarefas são enviadas, o pool aumenta automaticamente. Conforme as tarefas são concluídas, as VMs são liberadas e a fórmula de dimensionamento automático reduz o pool.

Esta fórmula reduz os nós dedicados, mas também pode ser modificada para aplicar à escala dos nós spot.

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;

Importante

Atualmente o Batch Service possui limitações na resolução das tarefas pendentes. Quando uma tarefa é adicionada ao trabalho, ela também é adicionada a uma fila interna usada pelo serviço do Lote para agendamento. Se a tarefa for excluída antes de ser agendada, ela poderá persistir dentro da fila, fazendo com que ela ainda seja contada em $PendingTasks. Essa tarefa excluída eventualmente será desmarcada da fila quando o Lote tiver a chance de efetuar pull de tarefas da fila para agendar com nós ociosos no pool do Lote.

Nós com preempção

Este exemplo cria um pool que começa com 25 nós spot. Toda vez que um nó spot sofre preempção, ele é substituído por um nó dedicado. Assim como no primeiro exemplo, a variável maxNumberofVMs impede que o pool tenha mais que 25 VMs. Este exemplo é útil para aproveitar as VMs spot e, ao mesmo tempo, garantir que apenas um número fixo de preempções ocorra durante a vida útil do pool.

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

Você aprenderá mais sobre como criar fórmulas de dimensionamento automático e verá mais exemplos de fórmulas de dimensionamento automático posteriormente neste artigo.

Variáveis

Você pode usar as variáveis definidas pelo serviço e definidas pelo usuário em suas fórmulas de dimensionamento automático.

As variáveis definidas pelo serviço são incorporadas ao serviço de Lote. Algumas variáveis definidas pelo serviço são de leitura e gravação e algumas são somente leitura.

Variáveis definidas pelo usuário são as variáveis que você definir. No exemplo anterior, $TargetDedicatedNodes e $PendingTasks são variáveis definidas pelo serviço, enquanto startingNumberOfVMs e maxNumberofVMs são variáveis definidas pelo usuário.

Observação

As variáveis definidas pelo serviço sempre são precedidas de um sinal de dólar ($). Para variáveis definidas pelo usuário, o cifrão é opcional.

As tabelas a seguir mostram as variáveis de leitura e gravação e de somente leitura definidas pelo serviço de Lote.

Variáveis definidas pelo serviço de leitura/gravação

É possível obter e definir os valores dessas variáveis definidas pelo serviço para gerenciar o número de nós de computação em um pool.

Variável Descrição
$TargetDedicatedNodes O número de nós de computação dedicados de destino para o pool. Especificado como um alvo porque um pool nem sempre pode atingir o número desejado de nós. Por exemplo, se o número alvo de nós dedicados for modificado por uma avaliação de dimensionamento automático antes que o pool atinja a meta inicial, talvez o pool não atinja a mata.

Um pool em uma conta criada no modo de serviço do Lote pode não atingir sua meta se a meta exceder um nó de conta do Lote ou uma cota principal. Um pool em uma conta criada no modo de assinatura do usuário pode não atingir sua meta se a meta exceder a cota básica compartilhada da assinatura.
$TargetLowPriorityNodes O número de nós de computação spot de destino para o pool. Especificado como um alvo porque um pool nem sempre pode atingir o número desejado de nós. Por exemplo, se o número alvo de nós Spot for modificado por uma avaliação de dimensionamento automático antes que o pool atinja a meta inicial, o pool pode não atingir a meta. Um pool também pode não atingir sua meta se a meta exceder um nó da conta do Lote ou uma cota principal.

Para obter mais informações sobre nós de computação spot, consulte Usar VMs de spot com o lote.
$NodeDeallocationOption A ação que ocorre quando nós de computação são removidos de um pool. Os valores possíveis são:
- requeue: o valor padrão. Finaliza as tarefas imediatamente e as coloca novamente na fila de trabalhos para que sejam reagendadas. Essa ação garante que o número de destino dos nós seja alcançado o mais rápido possível. No entanto, pode ser menos eficiente, porque todas as tarefas em execução são interrompidas e, em seguida, devem ser reiniciadas.
- terminate: encerra imediatamente as tarefas e as remove da fila de trabalhos.
- taskcompletion: aguarda a conclusão das tarefas atualmente em execução e, em seguida, remove o nó do pool. Use essa opção para evitar que as tarefas sejam interrompidas e recolocadas na fila, desperdiçando o trabalho que a tarefa já tinha feito.
- retaineddata: espera que todos os dados locais retidos pela tarefa no nó sejam limpos antes de remover o nó do pool.

Observação

A variável $TargetDedicatedNodes também pode ser especificada por meio do alias $TargetDedicated. De modo semelhante, é possível especificar a variável $TargetLowPriorityNodes por meio do alias $TargetLowPriority. Se a variável totalmente nomeada e seu alias forem definidos pela fórmula, o valor atribuído à variável totalmente nomeada terá precedência.

Variáveis somente leitura definidas pelo serviço

É possível obter o valor dessas variáveis definidas pelo serviço para fazer ajustes que se baseiam em métricas do serviço de Lote.

Importante

As tarefas de liberação de trabalho não estão atualmente incluídas nas variáveis que fornecem contagens de tarefas, como $ActiveTasks e $PendingTasks. Dependendo da fórmula de dimensionamento automático, isso pode resultar na remoção de nós, sem nós disponíveis para executar tarefas de liberação de trabalho.

Dica

Essas variáveis definidas pelo serviço e de somente leitura são objetos que fornecem vários métodos para acessar os dados associados a cada uma. Para obter mais informações, consulte Obter amostras de dados a seguir neste artigo.

Variável Descrição
$CPUPercent O percentual médio de utilização da CPU.
$WallClockSeconds O número de segundos consumidos. Desativado após 31 de março de 2024.
$MemoryBytes O número médio de megabytes usados. Desativado após 31 de março de 2024.
$DiskBytes O número médio de gigabytes usado nos discos locais. Desativado após 31 de março de 2024.
$DiskReadBytes O número de bytes lidos. Desativado após 31 de março de 2024.
$DiskWriteBytes O número de bytes gravados. Desativado após 31 de março de 2024.
$DiskReadOps A contagem de operações de leitura de disco executadas. Desativado após 31 de março de 2024.
$DiskWriteOps A contagem de operações de gravação em disco executadas. Desativado após 31 de março de 2024.
$NetworkInBytes O número de bytes de entrada. Desativado após 31 de março de 2024.
$NetworkOutBytes O número de bytes de saída. Desativado após 31 de março de 2024.
$SampleNodeCount A contagem de nós de computação. Desativado após 31 de março de 2024.
$ActiveTasks O número de tarefas que está pronto para executar, mas ainda não está executando. Isso inclui todas as tarefas que estão no estado ativo e cujas dependências foram satisfeitas. Todas as tarefas no estado ativo, mas cujas dependências não foram satisfeitas, são excluídas da contagem $ActiveTasks. Para uma tarefa com várias instâncias, $ActiveTasks inclui o número de instâncias definidas na tarefa.
$RunningTasks O número de tarefas em estado de execução.
$PendingTasks A soma de $ActiveTasks e $RunningTasks.
$SucceededTasks O número de tarefas que foram concluídas com êxito.
$FailedTasks O número de tarefas que falharam.
$TaskSlotsPerNode O número de slots de tarefas que podem ser usados para executar tarefas simultâneas em um único nó de computação no pool.
$CurrentDedicatedNodes O número atual de nós de computação dedicados.
$CurrentLowPriorityNodes O número atual de nós de computação spot incluindo nós que tenham sofrido preempção.
$UsableNodeCount O número de nós de computação utilizáveis.
$PreemptedNodeCount O número de nós no pool que estão em estado de prevenção.

Aviso

A seleção de variáveis definidas pelo serviço será desativada após 31 de março de 2024, conforme observado na tabela acima. Após a data de desativação, essas variáveis definidas pelo serviço não serão mais preenchidas com dados de exemplo. Descontinue o uso dessas variáveis antes dessa data.

Observação

Use $RunningTasks ao colocar em escala com base no número de tarefas em execução em um ponto no tempo e $ActiveTasks ao colocar em escala com base no número de tarefas que estão na fila para serem executadas.

Tipos

As fórmulas de dimensionamento automático dão suporte aos seguintes tipos:

  • double
  • doubleVec
  • doubleVecList
  • string
  • timestamp – uma estrutura composta que contém os seguintes membros:
    • ano
    • month (1-12)
    • day (1-31)
    • weekday (no formato de número, por exemplo, 1 para segunda-feira)
    • hour (no formato de número de 24 horas, por exemplo, 13 significa 1 PM)
    • 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

Operações

Essas operações são permitidas nos tipos listados na seção anterior.

Operação Operadores com suporte Tipo de resultado
double operador double +, -, *, / double
double operador timeinterval * timeinterval
doubleVec operador double +, -, *, / doubleVec
doubleVec operador doubleVec +, -, *, / doubleVec
timeinterval operador double *, / timeinterval
timeinterval operador timeinterval +, - timeinterval
timeinterval operador timestamp + timestamp
timestamp operador timeinterval + timestamp
timestamp operador timestamp - timeinterval
operador double -, ! double
operador timeinterval - timeinterval
double operador double <, <=, ==, >=, >, != double
string operador string <, <=, ==, >=, >, != double
timestamp operador timestamp <, <=, ==, >=, >, != double
timeinterval operador timeinterval <, <=, ==, >=, >, != double
double operador double &&, || double

Testar um duplo com um operador ternário (double ? statement1 : statement2), resulta em diferente de zero como true e zero como false.

Funções

Você pode usar essas funções predefinidas ao definir uma fórmula de dimensionamento automático.

Função Tipo de retorno Descrição
avg(doubleVecList) double Retorna o valor médio de todos os valores em doubleVecList.
ceil(double) double Retorna o menor valor inteiro que não seja menor que o dobro.
ceil(doubleVecList) doubleVec Retorna o ceil de componentes do doubleVecList.
floor(double) double Retorna o maior valor inteiro que não seja superior ao dobro.
floor(doubleVecList) doubleVec Retorna o floor de componentes do doubleVecList.
len(doubleVecList) double Retorna o comprimento do vetor criado por meio de doubleVecList.
lg(double) double Retorna o logaritmo na base 2 do double.
lg(doubleVecList) doubleVec Retorna o lg de componentes do doubleVecList.
ln(double) double Retorna o logaritmo natural do double.
ln(doubleVecList) doubleVec Retorna o ln de componentes do doubleVecList.
log(double) double Retorna o logaritmo na base 10 do double.
log(doubleVecList) doubleVec Retorna o log de componentes do doubleVecList.
max(doubleVecList) double Retorna o valor máximo em doubleVecList.
min(doubleVecList) double Retorna o valor mínimo em doubleVecList.
norm(doubleVecList) double Retorna a norma dupla do vetor criado por meio de doubleVecList.
percentile(doubleVec v, double p) double Retorna o elemento percentil do vetor v.
rand() double Retorna um valor aleatório entre 0,0 e 1,0.
range(doubleVecList) double Retorna a diferença entre os valores mínimo e máximo em doubleVecList.
round(double) double Retorna o valor inteiro mais próximo ao dobro (no formato de ponto flutuante), arredondando os casos de metade para longe de zero.
round(doubleVecList) doubleVec Retorna o round de componentes do doubleVecList.
std(doubleVecList) double Retorna o desvio padrão da amostra dos valores em doubleVecList.
stop() Interrompe a avaliação da expressão de dimensionamento automático.
sum(doubleVecList) double Retorna a soma de todos os componentes em doubleVecList.
time(string dateTime="") timestamp Retorna o carimbo de data/hora do horário atual se nenhum parâmetro for passado ou o carimbo de data/hora da cadeia de caracteres dateTime se algum parâmetro passar. Os formatos de dateTime com suporte são W3C-DTF e RFC1123.
val(doubleVec v, double i) double Retorna o valor do elemento que está no local i do vetor v com um índice inicial de zero.

Algumas das funções descritas na tabela anterior podem aceitar uma lista como um argumento. A lista separada por vírgulas é qualquer combinação de double e doubleVec. Por exemplo:

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

O valor de doubleVecList é convertido em um único doubleVec antes da avaliação. Por exemplo, se v = [1,2,3], então chamar avg(v) equivale a chamar avg(1,2,3). Chamar avg(v, 7) é equivalente a chamar avg(1,2,3,7).

Métricas

Você pode usar métricas de recursos e tarefas ao definir uma fórmula. Você ajustará o número alvo de nós dedicados no pool com base nos dados de métrica que você obtiver e avaliar. Para obter mais informações sobre cada métrica, consulte a seção Variáveis.

Métrica Descrição
Recurso As métricas de recurso são baseadas na CPU, na largura de banda, no uso de memória dos nós de computação e no número de nós.

Essas variáveis definidas pelo serviço são úteis para fazer ajustes com base na contagem de nós:
- $TargetDedicatedNodes
- $TargetLowPriorityNodes
- $CurrentDedicatedNodes
- $CurrentLowPriorityNodes
- $PreemptedNodeCount
- $UsableNodeCount

Estas variáveis definidas pelo serviço são úteis para fazer ajustes com base no uso de recursos do nó:
- $CPUPercent
- $WallClockSeconds
- $MemoryBytes
- $DiskBytes
- $DiskReadBytes
- $DiskWriteBytes
- $DiskReadOps
- $DiskWriteOps
- $NetworkInBytes
- $NetworkOutBytes
Tarefa As métricas de tarefa são baseadas no status das tarefas, como Ativa, Pendente e Concluída. As variáveis definidas pelo serviço a seguir são úteis para fazer ajustes no tamanho do pool com base nas métricas da tarefa:
- $ActiveTasks
- $RunningTasks
- $PendingTasks
- $SucceededTasks
- $FailedTasks

Obter dados de exemplo

A principal operação de uma fórmula de dimensionamento automático é obter dados de métricas de tarefas e recursos (amostras) e, em seguida, ajustar o tamanho do pool com base nesses dados. Assim, é importante ter um claro entendimento de como as fórmulas de dimensionamento automático interagem com exemplos.

Métodos

As fórmulas de dimensionamento automático agem em exemplos de dados de métrica fornecidos pelo serviço de Lote. Uma fórmula aumenta ou diminui os nós de computação do pool com base nos valores obtidos. Variáveis definidas pelo serviço são objetos que fornecem métodos para acessar os dados associados a esse objeto. Por exemplo, a expressão a seguir mostra uma solicitação para obter os últimos cinco minutos de uso da CPU:

$CPUPercent.GetSample(TimeInterval_Minute * 5)

Os métodos a seguir podem ser usados para obter dados de amostra sobre as variáveis definidas pelo serviço.

Método Descrição
GetSample() O método GetSample() retorna um vetor de exemplos de dados.

Uma amostra é de 30 segundos de dados de métrica. Em outras palavras, os exemplos são obtidos a cada 30 segundos. Mas, conforme observado abaixo, há um atraso entre o momento em que uma amostra é coletada e o momento em que ela fica disponível para uma fórmula. Assim, nem todas as amostras de um determinado período de tempo podem estar disponíveis para avaliação por uma fórmula.

- doubleVec GetSample(double count): especifica o número de amostras a serem obtidas das amostras mais recentes que foram coletadas. GetSample(1) retorna a última amostra disponível. No entanto, para métricas como $CPUPercent, GetSample(1) não deve ser usado porque é impossível saber quando a amostra foi coletada. Ela pode ser recente ou, devido a problemas do sistema, muito mais antiga. Nesses casos, é melhor usar um intervalo de tempo, conforme mostrado abaixo.

- doubleVec GetSample((timestamp or timeinterval) startTime [, double samplePercent]): especifica um período para coletar os dados de amostra. Opcionalmente, também especifica a porcentagem de amostras que devem estar disponíveis no período de tempo solicitado. Por exemplo, $CPUPercent.GetSample(TimeInterval_Minute * 10) retornaria 20 amostras, se todas as amostras nos últimos 10 minutos estiverem presentes no histórico CPUPercent. Se o último minuto do histórico não estivesse disponível, apenas 18 amostras seriam retornadas. Nesse caso, $CPUPercent.GetSample(TimeInterval_Minute * 10, 95) falharia porque apenas 90% das amostras estão disponíveis, mas $CPUPercent.GetSample(TimeInterval_Minute * 10, 80) teria êxito.

- doubleVec GetSample((timestamp or timeinterval) startTime, (timestamp or timeinterval) endTime [, double samplePercent]): especifica um período para a coleta de dados, com um horário de início e um horário de término. Conforme mencionado acima, há um atraso entre o momento em que uma amostra é coletada e o momento em que ela fica disponível para uma fórmula. Considere esse atraso ao utilizar o método GetSample. Veja GetSamplePercent abaixo.
GetSamplePeriod() Retorna o período das amostras que foram colhidas de um conjunto de dados históricos de exemplo.
Count() Retorna o número total de amostras no histórico de métricas.
HistoryBeginTime() Retorna o carimbo de data/hora da amostra de dados mais antiga disponível para a métrica.
GetSamplePercent() Retorna a porcentagem de exemplos disponíveis para um determinado intervalo de tempo. Por exemplo, doubleVec GetSamplePercent( (timestamp or timeinterval) startTime [, (timestamp or timeinterval) endTime] ). Como o método GetSample falhará se o percentual de amostras retornadas for menor do que o samplePercent especificado, você poderá usar o método GetSamplePercent para verificar primeiro. Em seguida, você pode executar uma ação alternativa se não houver exemplos suficientes, sem interromper a avaliação do dimensionamento automático.

Exemplos

O serviço de Lote periodicamente obtém exemplos de métricas das tarefas e recursos e disponibiliza-os para suas fórmulas de autoescala. Esses exemplos são gravados a cada 30 segundos pelo serviço de Lote. No entanto, normalmente há algum atraso entre quando essas amostras foram gravadas e quando elas são disponibilizadas para (e lidas por) suas fórmulas de dimensionamento automático. Além disso, as amostras podem não ser registradas em um intervalo específico devido a fatores como problemas de rede ou outros problemas de infraestrutura.

Exemplo de porcentagem

Quando samplePercent é passado para o método GetSample() ou o método GetSamplePercent() é chamado, a porcentagem irá se referir a uma comparação entre o número total possível de amostras gravadas pelo serviço de Lote e o número de amostras disponíveis para sua fórmula de dimensionamento automático.

Vejamos um intervalo de tempo de 10 minutos como exemplo. Como as amostras são registradas a cada 30 segundos dentro desse intervalo de tempo de 10 minutos, o número total máximo de amostras registradas pelo Lote seria de 20 amostras (2 por minuto). No entanto, devido à latência inerente ao mecanismo de geração de relatórios e a outros problemas no Azure, pode haver apenas 15 amostras disponíveis para leitura na sua fórmula de dimensionamento automático. Assim, por exemplo, para esse período de 10 minutos, apenas 75% do número total de amostras registradas pode estar disponível para sua fórmula.

GetSample() e intervalos de exemplo

Suas fórmulas de dimensionamento automático crescem aumentam e diminuem seus pools adicionando ou removendo nós. Como os nós custam dinheiro, certifique-se de que suas fórmulas utilizem um método inteligente de análise baseado em dados suficientes. É recomendável que você utilize uma análise de tipo de tendência em suas fórmulas. Este tipo aumenta e diminui seus pools baseado em uma variedade de exemplos coletados.

Para fazer isso, utilize GetSample(interval look-back start, interval look-back end) para retornar um vetor de exemplos:

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

Quando o Lote avalia a linha acima, ele retorna um intervalo de amostras como um vetor de valores. Por exemplo:

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

Depois de coletar o vetor de amostras, você pode usar funções como min(), max(), e avg() para derivar os valores significativos do intervalo coletado.

Para ter mais segurança, você pode forçar uma avaliação de fórmula para falhar, se menos de uma determinada porcentagem de amostra estiver disponível por um período de tempo específico. Ao forçar uma avaliação de fórmula a falhar, você orientará o Lote a interromper outras avaliações da fórmula se o percentual especificado de amostras não estiver disponível. Nesse caso, nenhuma alteração é feita ao tamanho do pool. Para especificar uma porcentagem requerida de exemplos para que a avaliação seja bem-sucedida, especifique-a como o terceiro parâmetro para GetSample(). Aqui, é especificado um requisito de 75% de exemplos:

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

Como pode haver um atraso na disponibilidade da amostra, você deve sempre especificar um intervalo de tempo com um horário de início retroativo maior que um minuto. Demora aproximadamente um minuto para que as amostras se propaguem pelo sistema, portanto, as amostras no intervalo (0 * TimeInterval_Second, 60 * TimeInterval_Second) podem não estar disponíveis. Repetindo, você pode usar o parâmetro de porcentagem de GetSample() para forçar um requisito de porcentagem de exemplo específico.

Importante

Recomendamos expressamente que você evite contar somente com GetSample(1) em suas fórmulas de dimensionamento automático. Isso ocorre porque GetSample(1) basicamente informa ao serviço de Lote: "Passe-me a última amostra que você tem, não importa há quanto tempo a recuperou". Como se trata apenas de uma amostra, e pode ser uma amostra antiga, talvez não represente o retrato mais amplo do estado da tarefa ou do recurso. Se você for mesmo usar GetSample(1), verifique se faz parte de uma instrução mais ampla e não apenas do ponto de dado do qual sua fórmula depende.

Criar uma fórmula de autoescala

Crie uma fórmula de autoescala formando instruções que usam os componentes acima e combine essas instruções em uma fórmula completa. Nesta seção, você cria um exemplo de fórmula de dimensionamento automático que pode realizar decisões de colocação em escala no mundo real e fazer ajustes.

Primeiro, vamos definir os requisitos para nossa nova fórmula de autoescala. A fórmula deve:

  • Aumente o número de nós de computação dedicados de destino em um pool, se o uso da CPU for alto.
  • Diminua o número de nós de computação dedicados de destino em um pool, quando o uso da CPU for baixo.
  • Sempre restrinja o número máximo de nós dedicados a 400.
  • Ao reduzir o número de nós, não remova os nós que estão executando tarefas. Se necessário, aguarde até que as tarefas tenham sido concluídas antes de remover os nós.

A primeira instrução na fórmula aumenta o número de nós durante o alto uso da CPU. Você define uma instrução que preenche uma variável definida pelo usuário ($totalDedicatedNodes) com um valor que é 110% do número alvo atual dos nós dedicados, mas somente se o uso médio mínimo da CPU durante os últimos 10 minutos estiver acima de 70%. Caso contrário, ela usa o valor para o número de nós dedicados atual.

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

Para diminuir o número de nós dedicados durante o baixo uso da CPU, a próxima declaração na fórmula define a mesma variável $totalDedicatedNodes para 90% do número alvo atual de nós dedicados, se o uso médio da CPU nos últimos 60 minutos foi inferior a 20 por cento. Caso contrário, ele usa o valor atual de $totalDedicatedNodes preenchido na instrução acima.

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

Agora, limite o número alvo de nós de computação dedicados a um máximo de 400.

$TargetDedicatedNodes = min(400, $totalDedicatedNodes);

Finalmente, certifique-se de que os nós não sejam removidos até que suas tarefas sejam concluídas.

$NodeDeallocationOption = taskcompletion;

Aqui está a fórmula completa:

$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;

Observação

Se desejar, você pode incluir comentários e quebras de linha nas cadeias de caracteres da fórmula. Também esteja ciente de que a falta de ponto-e-vírgula pode resultar em erros de avaliação.

Intervalo de dimensionamento automático

Por padrão, o serviço de Lote ajusta o tamanho do pool de acordo com sua fórmula de autoescala a cada 15 minutos. Esse intervalo é configurável utilizando as seguintes propriedades de pool:

O intervalo mínimo é de cinco minutos e o máximo é de 168 horas. Se um intervalo fora deste intervalo for especificado, o serviço de Lote retornará um erro 400 Solicitação Incorreta.

Observação

Atualmente, o dimensionamento automático não está projetado para responder a alterações em menos de um minuto, mas para ajustar o tamanho de seu pool gradativamente conforme você executa uma carga de trabalho.

Criar um pool habilitado para dimensionamento automático com os SDKs do Lote

É possível configurar o dimensionamento automático do pool usando qualquer um dos SDKs do Lote, a API REST do Lote, os cmdlets do PowerShell do Lote e a CLI do Lote. Nesta seção, há exemplos de .NET e Python.

.NET

Para criar um pool habilitado para dimensionamento automático em .NET, siga as etapas a seguir:

  1. Crie o pool com BatchClient.PoolOperations.CreatePool.
  2. Defina a propriedade CloudPool.AutoScaleEnabled como true.
  3. Defina a propriedade CloudPool.AutoScaleFormula com a fórmula de autoescala.
  4. (Opcional) Defina a propriedade CloudPool.AutoScaleEvaluationInterval (o padrão é de 15 minutos).
  5. Confirmar o pool com CloudPool.Commit ou CommitAsync.

O exemplo a seguir cria um pool habilitado para dimensionamento automático em .NET. A fórmula de dimensionamento automático do pool define o número de nós dedicados de destino para 5 às segundas-feiras e para 1 em todos os outros dias da semana. O intervalo de autoescala é definido como 30 minutos. Neste e nos outros snippets C# deste artigo, myBatchClient é uma instância corretamente inicializada da classe 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();

Importante

Ao criar um pool habilitado para dimensionamento automático, não especifique o parâmetro targetDedicatedNodes ou o parâmetro targetLowPriorityNodes na chamada para CreatePool. Em vez disso, especifique as propriedades AutoScaleEnabled e AutoScaleFormula no pool. Os valores para essas propriedades determinam o número de destino de cada tipo de nó.

Para redimensionar manualmente um pool habilitado para dimensionamento automático (por exemplo, com BatchClient.PoolOperations.ResizePoolAsync), você deve primeiro desabilitar o dimensionamento automático no pool e depois redimensioná-lo.

Dica

Para obter mais exemplos do uso do SDK do .NET, confira Repositório de Início Rápido do .NET do Lote no GitHub.

Python

Para criar um pool habilitado para dimensionamento automático com o SDK do Python:

  1. Crie um pool e especifique sua configuração.
  2. Adicione o pool ao cliente de serviço.
  3. Habilite o dimensionamento automático no pool escrevendo uma fórmula.

O exemplo a seguir ilustra essas etapas.

# 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)

Dica

Para obter mais exemplos de uso do SDK do Python, consulte o Repositório de Início Rápido do Python do Lote no GitHub.

Habilitar autoescala em um pool existente

Cada SDK do Lote fornece uma maneira de habilitar o dimensionamento automático. Por exemplo:

Ao habilitar o dimensionamento automático em um pool existente, lembre-se:

  • Se o dimensionamento automático estiver atualmente desabilitado no pool, você deverá especificar uma fórmula de dimensionamento automático válida ao emitir a solicitação. Opcionalmente, é possível especificar um intervalo de dimensionamento automático. Se você não especificar um intervalo, será usado o valor padrão de 15 minutos.
  • Se o dimensionamento automático estiver atualmente habilitado no pool, você poderá especificar uma nova fórmula, um novo intervalo ou ambos. É necessário especificar pelo menos uma dessas propriedades.
    • Se você especificar um novo intervalo de dimensionamento automático, o agendamento existente é interrompido e um novo agendamento será iniciado. A hora de início do novo agendamento é a hora em que a solicitação para habilitar o dimensionamento automático foi emitida.
    • Se você omitir a fórmula ou o intervalo de dimensionamento automático, o serviço de Lote continuará a usar o valor atual dessa configuração.

Observação

Se você especificou valores para os parâmetros targetDedicatedNodes ou targetLowPriorityNodes do método CreatePool quando criou o pool em .NET ou para os parâmetros comparáveis em outra linguagem, esses valores serão ignorados quando a fórmula de dimensionamento automático for avaliada.

Este exemplo C# usa a biblioteca .NET do Lote para habilitar o dimensionamento automático em um pool existente.

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

Atualizar uma fórmula de autoescala

Para atualizar a fórmula em um pool habilitado para autoescala existente, chame a operação para habilitar o novamente o dimensionamento automático com a nova fórmula. Por exemplo, se o dimensionamento automático já estiver habilitado em myexistingpool quando o seguinte código .NET for executado, sua fórmula de autoescala será substituída pelo conteúdo de myNewFormula.

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

Atualizar o intervalo de autoescala

Para atualizar o intervalo de avaliação de autoescala de um pool habilitado para autoescala existente, chame a operação para habilitar novamente o dimensionamento automático com o novo intervalo. Por exemplo, para definir o intervalo de avaliação de autoescala para 60 minutos para um pool que já está habilitado para autoescala em .NET:

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

Avaliar uma fórmula de autoescala

Você pode avaliar uma fórmula antes de aplicá-la a um pool. Isso permite testar os resultados da fórmula antes de colocá-la em produção.

Antes de avaliar uma fórmula de dimensionamento automático, você deve primeiro habilitar o dimensionamento automático no pool com uma fórmula válida, como a fórmula de uma linha $TargetDedicatedNodes = 0. Depois, use um dos seguintes itens para avaliar a fórmula que você deseja testar:

  • BatchClient.PoolOperations.EvaluateAutoScale ou EvaluateAutoScaleAsync

    Estes métodos .NET do Lote exigem a identificação de um pool existente e uma cadeia de caracteres que contém a fórmula de autoescala a ser avaliada.

  • Avaliar uma fórmula de autoescala

    Nessa solicitação da API REST, especifique a ID do pool no URI e a fórmula de autoescala no elemento autoScaleFormula do corpo da solicitação. A resposta da operação contém quaisquer informações de erro que possam estar relacionadas à fórmula.

O seguinte exemplo .NET do Lote avalia uma fórmula de dimensionamento automático. Se o pool ainda não usa o dimensionamento automático, ative-o primeiro.

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

A avaliação bem-sucedida da fórmula mostrada neste snippet de código produz resultados semelhantes a:

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

Obter informações sobre execuções de autoescala

É recomendável verificar periodicamente a avaliação do serviço de Lote de sua fórmula de dimensionamento automático. Para isso, obtenha (ou atualize) uma referência para o pool e examine as propriedades da última execução de dimensionamento automático.

No .NET do Lote, a propriedade CloudPool.AutoScaleRun possui várias propriedades que fornecem informações sobre a última execução de dimensionamento automático executada no pool:

Na API REST, a Obter informações sobre uma solicitação de pool retorna informações sobre o pool, que incluem as informações mais recentes da execução da escala automática mais recentes na propriedade autoScaleRun.

O exemplo C# a seguir utiliza a biblioteca .NET do Lote para imprimir informações sobre a última execução de dimensionamento automático executada no pool myPool.

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

Saída de exemplo do exemplo anterior:

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:

Obter histórico de execuções de dimensionamento automático usando eventos de dimensionamento automático do pool

Você também pode verificar o histórico de dimensionamento automático ao consultar PoolAutoScaleEvent. O lote emite esse evento para registrar cada ocorrência de avaliação e execução de fórmula de dimensionamento automático, o que pode ser útil para solucionar possíveis problemas.

Exemplo de evento para 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": []
    }
}

Fórmulas de autoescala de exemplo

Vejamos algumas fórmulas que mostram diferentes maneiras de ajustar a quantidade de recursos de computação em um pool.

Exemplo 1: ajuste baseado no tempo

Suponha que você deseja ajustar o tamanho do pool baseado no dia da semana e hora do dia. Este exemplo mostra como aumentar ou diminuir adequadamente o número de nós no pool.

A fórmula primeiro obtém a hora atual. Se trata-se de um dia da semana (1-5) e durante o horário de trabalho (8h-18h), o tamanho do pool de destino é definido como 20 nós. Caso contrário, ele é definido como 10 nós.

$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;

É possível ajustar $curTime para refletir o fuso horário local. Basta adicionar time() ao produto de TimeZoneInterval_Hour e a diferença UTC. Por exemplo, use $curTime = time() + (-6 * TimeInterval_Hour); para o MDT (Hora de Verão das Montanhas). Tenha em mente que o deslocamento precisa ser ajustado no início e no final do horário de verão, se aplicável.

Exemplo 2: ajuste baseado em tarefa

Neste exemplo C#, o tamanho do pool é ajustado com base no número de tarefas na fila. Tanto os comentários quanto as quebras de linha estão incluídos nas sequências de caracteres da fórmula.

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

Exemplo 3: contabilização de tarefas paralelas

Esse exemplo C# ajusta o tamanho do pool com base no número de tarefas. Essa fórmula também leva em consideração o valor de TaskSlotsPerNode definido para o pool. Essa abordagem é útil em situações nas quais a execução de tarefas paralelas foi habilitada em seu pool.

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

Exemplo 4: definindo um tamanho de pool inicial

Este exemplo mostra um exemplo C# com uma fórmula de dimensionamento automático que define o tamanho do pool para um número especificado de nós por um período de tempo inicial. Depois disso, ele ajusta o tamanho do pool com base no número de tarefas ativas e em execução.

Especificamente, a fórmula faz o seguinte:

  • Define o tamanho do pool inicial como quatro nós
  • Não ajusta o tamanho do pool nos primeiros 10 minutos do ciclo de vida do pool.
  • Após 10 minutos, obtém o valor máximo do número de tarefas ativas e em execução nos últimos 60 minutos
    • Se ambos os valores forem 0, indicando que nenhuma tarefa estava em execução ou ativa nos últimos 60 minutos, o tamanho do pool será definido como 0.
    • Se um dos valores for maior do que zero, nenhuma alteração será feita
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);

Próximas etapas