建立公式,以自動調整 Batch 集區中的計算節點

Azure Batch 可根據您定義的參數自動調整集區,以節省您的時間與金錢。 使用自動調整,Batch 會隨著工作需求增加,動態地將節點新增至集區,以及隨著工作需求減少而移除計算節點。

若要在計算節點的集區上啟用自動調整,您可讓此集區與您定義的「自動調整公式」產生關聯。 Batch 服務會使用自動調整公式來判斷執行您的工作負載所需的節點數目。 這些節點可能是專用節點或 Azure Spot 節點。 Batch 會定期檢閱服務計量資料,並使用該資料來根據公式和您定義的間隔來調整集區中的節點數目。

您可以在建立集區時啟用自動調整功能,或將其套用至現有的集區。 Batch 可讓您在將公式指派給集區之前評估公式,以及監視自動調整執行的狀態。 設定具有自動調整功能的集區後,您稍後可以對公式進行變更。

重要

當您建立 Batch 帳戶時,您可以指定集區配置模式,該設定會決定集區是配置在 Batch 服務訂用帳戶 (預設值),或是您的使用者訂用帳戶。 如果您使用預設 Batch 服務設定來建立 Batch 帳戶,則您的帳戶受限為可用於處理的核心數目上限。 Batch 服務只會將計算節點調整為最多達到該核心限制。 基於這個理由,Batch 服務不會達到自動調整公式所指定的目標計算節點數目。 如需了解如何檢視和增加帳戶配額,請參閱 Azure Batch 服務的配額和限制

如果您以使用者訂用帳戶模式建立您的帳戶,則您的帳戶會共用訂用帳戶的核心配額。 如需詳細資訊,請參閱 Azure 訂用帳戶和服務限制、配額與條件約束中的 虛擬機器限制

自動調整公式

自動調整公式是您定義的字串值,其中包含一或多個陳述式。 自動調整公式會指派給集區的 autoScaleFormula 元素 (Batch REST) 或 CloudPool.AutoScaleFormula 屬性 (Batch .NET)。 Batch 集區會使用您的公式來決定集區中可供下一個間隔處理的目標計算節點數目。 公式字串不得超過 8 KB、最多只能包含 100 個陳述式 (以分號隔開),而且可以包含換行和註解。

您可以將自動調整公式視為 Batch 自動調整「語言」。公式陳述式是自由格式的運算式,可以同時包括服務定義的變數 (Batch 服務所定義的變數) 和使用者定義的變數。 公式可以使用內建類型、運算子和函式對這些值執行各種作業。 例如,陳述式可能會採用下列格式:

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

公式通常包含多個陳述式,其可對在先前陳述式中取得的值執行作業。 例如,首先您會取得 variable1 的值,然後將其傳遞至函式以填入 variable2

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

在您的自動調整公式中包含這些陳述式,以達成目標計算節點數目。 專用節點和 Spot 節點各自有自己的目標設定。 自動調整公式可以包含專用節點目標值、Spot 節點目標值,或同時包含兩者。

目標節點數目可能會更高、更低,或與集區中該類型目前的節點數目相同。 Batch 服務會在特定自動調整間隔評估集區的自動調整公式。 Batch 會將集區中每個節點類型的目標數目調整為自動調整公式在評估時指定的數目。

自動調整公式範例

以下是兩個自動調整公式的範例,可調整以適用於大部分情況。 您可以依照需求調整範例公式中的 startingNumberOfVMsmaxNumberofVMs 變數。

暫止工作

使用此自動調整公式,一開始會建立包含單一 VM 的集區。 $PendingTasks 計量會定義執行中或已排入佇列的工作數目。 公式會尋找過去 180 秒內的平均擱置中工作數目,並據以設定 $TargetDedicatedNodes 變數。 公式會確保目標專用節點數目絕不會超出 25 部 VM。 集區會隨著新工作的提交而自動成長。 隨著工作完成,VM 會變成可用,且自動調整公式會縮小集區。

此公式會調整專用節點,但是可加以修改,套用來調整 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;

重要

Batch 服務目前有解決擱置中工作的限制。 將工作新增至作業時,也會將該工作新增至 Batch 服務用於排程的內部佇列中。 如果工作在排程之前遭到刪除,工作可能會保存在佇列中,導致仍將該工作計入 $PendingTasks。 當 Batch 有機會從佇列提取工作,以使用 Batch 集區中的閒置節點進行排程時,最終會將這個遭刪除的工作從佇列中清除。

先佔節點

這個範例建立的集區最初有 25 個 Spot 節點。 Spot 節點每次被先佔就會換成專用節點。 在第一個範例中,maxNumberofVMs 變數會防止集區超過 25 個 VM。 這個範例有助於使用 Spot VM,同時確保集區的存留期只發生固定次數的先佔。

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

您將深入了解如何建立自動調整公式,並查看本主題稍後的更多自動調整公式範例

變數

您可以在自動調整公式中同時使用服務定義使用者定義的變數。

服務定義的變數內建在 Batch 服務中。 有些服務定義的變數是讀寫,有些是唯讀。

使用者定義的變數是您定義的變數。 在上述範例中,$TargetDedicatedNodes$PendingTasks 是服務定義的變數,而 startingNumberOfVMsmaxNumberofVMs 則是使用者定義的變數。

注意

服務定義的變數前面一律會加上貨幣符號 ($)。 針對使用者定義的變數而言,貨幣符號是選擇性的。

下表顯示 Batch 服務所定義的讀寫和唯讀變數。

讀寫服務定義變數

您可以取得並設定這些這些服務定義的變數值,以管理集區中的計算節點。

變數 描述
$TargetDedicatedNodes 集區之專用計算節點的目標數目。 指定作為目標,因為集區可能不一定會達到想要的節點數目。 例如,如果在集區達到初始目標之前,自動調整評估修改目標專用節點數目,則集區可能未達到目標。

如果目標超過 Batch 帳戶節點或核心配額,以 Batch 服務模式建立之帳戶中的集區可能未達到其目標。 如果目標超過訂用帳戶的共用核心配額,以使用者訂用帳戶模式建立之帳戶中的集區可能未達到其目標。
$TargetLowPriorityNodes 集區之 Spot 計算節點的目標數目。 指定作為目標,因為集區可能不一定會達到想要的節點數目。 例如,如果在集區達到初始目標之前,自動調整評估修改目標 Spot 節點數目,則該集區可能未達到目標。 如果目標超過 Batch 帳戶節點或核心配額,則集區也可能未達到其目標。

如需 Spot 計算節點的詳細資訊,請參閱使用 Spot VM 搭配 Batch
$NodeDeallocationOption 計算節點從集區移除時所發生的動作。 可能的值包括:
- requeue:預設值。 立即結束工作,並將工作放回作業佇列以重新排程。 此動作可確保儘快達到目標節點數目。 不過,因為任何執行中的工作都會中斷,然後必須將其重新啟動,所以效率可能較低。
- terminate:立即結束工作,並從作業佇列移除這些工作。
- taskcompletion:等待目前執行中的工作完成,然後再從集區中移除該節點。 使用此選項可避免工作中斷和重新排入佇列,而浪費工作已完成的任何工作。
- retaineddata:等待所有本機工作保留在節點上的資料先清除,再從集區移除節點。

注意

您也可以使用別名 $TargetDedicated 來指定 $TargetDedicatedNodes 變數。 同樣地,您可以使用別名 $TargetLowPriority 來指定 $TargetLowPriorityNodes 變數。 如果完整命名的變數及其別名都由公式設定,則以指派給完整命名變數的值為優先。

唯讀服務定義變數

您可以取得這些服務定義的變數值,以根據 Batch 服務提供的計量進行調整。

重要

作業解除工作目前未包含在提供工作計數的變數中,例如 $ActiveTasks$PendingTasks。 視您的自動調整公式而定,這可能導致節點遭到移除,而沒有可供執行作業發行工作使用的節點。

提示

這些服務定義的唯讀變數是可提供各種方法來存取相關聯資料的「物件」。 如需詳細資訊,請參閱本文稍後的取得範例資料

變數 描述
$CPUPercent CPU 使用量的平均百分比。
$WallClockSeconds 已耗用的秒數。 在 2024 年 3 月 31 日之後淘汰。
$MemoryBytes 已使用的平均 MB 數目。 在 2024 年 3 月 31 日之後淘汰。
$DiskBytes 已在本機磁碟上使用的平均 GB 數目。 在 2024 年 3 月 31 日之後淘汰。
$DiskReadBytes 讀取的位元組數。 在 2024 年 3 月 31 日之後淘汰。
$DiskWriteBytes 寫入的位元組數目。 在 2024 年 3 月 31 日之後淘汰。
$DiskReadOps 已執行的讀取磁碟作業計數。 在 2024 年 3 月 31 日之後淘汰。
$DiskWriteOps 已執行的寫入磁碟作業計數。 在 2024 年 3 月 31 日之後淘汰。
$NetworkInBytes 輸入位元組的數目。 在 2024 年 3 月 31 日之後淘汰。
$NetworkOutBytes 輸出位元組的數目。 在 2024 年 3 月 31 日之後淘汰。
$SampleNodeCount 計算節點的計數。 在 2024 年 3 月 31 日之後淘汰。
$ActiveTasks 準備好執行但還未執行的工作數目。 這包含處於作用中狀態,而且已滿足其相依性的所有工作。 處於作用中狀態但未滿足其相依性的任何工作會從 $ActiveTasks 計數排除。 若為多重執行個體工作,$ActiveTasks 將包含工作上設定的執行個體數目。
$RunningTasks 處於執行中狀態的工作數目。
$PendingTasks $ActiveTasks$RunningTasks 的總和。
$SucceededTasks 已成功完成的工作數目。
$FailedTasks 失敗的工作數目。
$TaskSlotsPerNode 可用於在集區中單一計算節點上執行並行工作的工作位置數目。
$CurrentDedicatedNodes 目前的專用計算節點數目。
$CurrentLowPriorityNodes 目前的 Spot 計算節點數目,包括任何已先佔的節點。
$UsableNodeCount 可用計算節點的數目。
$PreemptedNodeCount 優先佔用狀態的集區中之節點數目。

警告

選取服務定義的變數將在 2024 年 3 月 31 日之後淘汰,如上表所述。 淘汰日期之後,這些服務定義的變數將不再填入範例資料。 請在此日期之前停止使用這些變數。

注意

根據某個時間點執行的工作數目進行調整時,請使用 $RunningTasks,而根據排入佇列要執行的工作數目進行調整時,則使用 $ActiveTasks

類型

自動調整公式支援下列類型:

  • double
  • doubleVec
  • doubleVecList
  • string
  • timestamp:包含下列成員的複合結構:
    • year
    • month (1-12)
    • day (1-31)
    • weekday (以數字格式表示,例如 1 代表星期一)
    • hour (以 24 小時制數字格式表示,例如 13 代表下午 1: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

Operations

上一節列出的類型允許這些作業。

作業 支援的運算子 結果類型
double 運算子 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
operator double -, ! double
operator timeinterval - timeinterval
double 運算子 double <、<=、==、=、>>、!= double
string string <、<=、==、=、>>、!= double
timestamp timestamp <、<=、==、=、>>、!= double
timeinterval 運算子 timeinterval <、<=、==、=、>>、!= double
double 運算子 double &&, || double

測試具有三元運算子的雙精度浮點數 (double ? statement1 : statement2) 時,非零為 true,而零則為 false

函式

您可以在定義自動調整公式時,使用這些預先定義的函式

函式 傳回類型 描述
avg(doubleVecList) double 傳回 doubleVecList 中所有值的平均值。
ceil(double) double 傳回不小於雙精度浮點數的最小整數值。
ceil(doubleVecList) doubleVec 傳回 doubleVecList 的全元件 ceil
floor(double) double 傳回不大於雙精度浮點數的最大整數值。
floor(doubleVecList) doubleVec 傳回 doubleVecList 的全元件 floor
len(doubleVecList) double 傳回 doubleVecList 建立的向量的長度。
lg(double) double 傳回 double 的對數底數 2。
lg(doubleVecList) doubleVec 傳回 doubleVecList 的全元件 lg
ln(double) double 傳回 double 的自然底數。
ln(doubleVecList) doubleVec 傳回 doubleVecList 的全元件 ln
log(double) double 傳回 double 的對數底數 10。
log(doubleVecList) doubleVec 傳回 doubleVecList 的全元件 log
max(doubleVecList) double 傳回 doubleVecList 中的最大值。
min(doubleVecList) double 傳回 doubleVecList 中的最小值。
norm(doubleVecList) double 傳回 doubleVecList 建立的向量的 2-norm。
percentile(doubleVec v, double p) double 傳回向量 v 的百分位數元素。
rand() double 傳回介於 0.0 到 1.0 之間的隨機值。
range(doubleVecList) double 傳回 doubleVecList 中最小和最大值之間的差異。
round(double) double 傳回與雙精度浮點數最接近的整數值 (浮點數格式),將中間的大小寫從零四捨五入。
round(doubleVecList) doubleVec 傳回 doubleVecList 的全元件 round
std(doubleVecList) double 傳回 doubleVecList 中值的標準差範例。
stop() 停止評估自動調整運算式。
sum(doubleVecList) double 傳回 doubleVecList 所有元件的總和。
time(string dateTime="") timestamp 如果未傳遞參數,則傳回目前時間的時間戳記,如果有傳遞參數,則為 dateTime 字串的時間戳記。 支援的 dateTime 格式為 W3C-DTF 和 RFC 1123。
val(doubleVec v, double i) double 傳回向量 v 中位置 i 的元素值,起始索引為零。

上表中所述的某些函式可以接受清單作為引數。 逗號分隔清單是 doubledoubleVec 的任意組合。 例如:

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)

計量

您可以在定義公式時同時使用資源和工作計量。 您會根據您取得和評估的度量資料來調整集區中專用節點的目標數目。 如需每個計量的詳細資訊,請參閱變數一節。

計量 描述
資源 資源計量是以計算節點的 CPU、頻寬和記憶體使用量以及節點數目為基礎。

這些服務定義的變數適合用於根據節點計數進行調整:
- $TargetDedicatedNodes
- $TargetLowPriorityNodes
- $CurrentDedicatedNodes
- $CurrentLowPriorityNodes
- $PreemptedNodeCount
- $UsableNodeCount

這些服務定義的變數適合用於根據節點資源使用量進行調整:
- $CPUPercent
- $WallClockSeconds
- $MemoryBytes
- $DiskBytes
- $DiskReadBytes
- $DiskWriteBytes
- $DiskReadOps
- $DiskWriteOps
- $NetworkInBytes
- $NetworkOutBytes
Task 工作計量是根據工作的狀態,例如作用中、暫止和已完成。 下列服務定義的變數適合用於根據工作度量進行集區大小調整:
- $ActiveTasks
- $RunningTasks
- $PendingTasks
- $SucceededTasks
- $FailedTasks

取得範例資料

自動調整公式的核心是要取得工作和資源計量資料 (樣本),然後根據該資料調整集區大小。 因此,請務必清楚了解自動調整公式如何與樣本互動。

方法

自動調整公式會對 Batch 服務所提供的計量資料樣本產生作用。 公式會根據取得的值擴大或縮減集區計算節點。 服務定義的變數是可提供方法來存取與該物件相關聯資料的物件。 例如,下列運算式顯示取得最後五分鐘的 CPU 使用量的要求:

$CPUPercent.GetSample(TimeInterval_Minute * 5)

下列方法可用來取得有關服務定義變數的樣本資料。

方法 描述
GetSample() GetSample() 方法會傳回資料樣本的向量。

一個樣本有 30 秒的度量資料。 換句話說,每隔 30 秒會取得範例。 如下所述,從收集樣本到可用於公式之間會延遲。 因此,並非一段指定時間內的所有樣本都可供公式評估。

- doubleVec GetSample(double count):指定要從最近收集的樣本中取得的樣本數。 GetSample(1) 會傳回最後一個可用的樣本。 不過,GetSample(1) 不得用於 $CPUPercent 之類的計量,因為不可能知道「何時」收集到樣本。 此範例可能是最新的,也可能因為系統問題,是更舊的。 在此情況下,最好使用如下所示的時間間隔。

- doubleVec GetSample((timestamp or timeinterval) startTime [, double samplePercent]):指定收集樣本資料的時間範圍。 它也會選擇性地指定在要求的時間範圍內必須可用的樣本數百分比。 例如,如果 CPUPercent 歷程記錄中有最後 10 分鐘的所有樣本,則 $CPUPercent.GetSample(TimeInterval_Minute * 10) 會傳回 20 個樣本。 如果最後一分鐘的歷程記錄無法使用,則只會傳回 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 方法進行檢查。 然後您可以在樣本不足時執行替代動作,而不暫停自動調整評估。

範例

Batch 服務會定期取得工作和資源計量的樣本,使其可供自動調整公式使用。 Batch 服務會每隔 30 秒記錄一次這些樣本。 不過,記錄樣本的時間與樣本可供自動調整公式使用 (與讀取) 的時間之間有所延遲。 此外,由於各種因素 (例如網路或其他基礎結構問題),可能未在特定間隔內記錄樣本。

樣本百分比

samplePercent 傳遞至 GetSample() 方法,或呼叫 GetSamplePercent() 方法時,percent 是指 Batch 服務可能記錄的樣本總數,與自動調整公式實際可用的樣本數目之間的比較。

讓我們以 10 分鐘的時間範圍為例。 因為會每隔 30 秒記錄一次樣本,所以在 10 分鐘的時間範圍內,Batch 服務所記錄的樣本總數就已達到 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);

Batch 評估上述程式碼後,其會以值的向量形式傳回樣本範圍。 例如:

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

收集樣本向量後,您便可使用 min()max()avg() 等函式,從所收集的範圍衍生出有意義的值。

為了謹慎行事,如果特定一段時間可用的樣本小於特定百分比,您可以強制公式評估為失敗。 強制公式評估為失敗會指示 Batch 在指定的樣本百分比無法使用時停止進一步評估公式。 在此情況下,不會變更集區大小。 若要指定評估成功所需的樣本百分比,請將其指定為 GetSample()的第三個參數。 以下指定了 75% 的樣本需求:

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

因為樣本可用性可能延遲,所以您應該一律指定回顧開始時間早於一分鐘的時間範圍。 樣本需要花大約一分鐘的時間才能傳播到整個系統,所以通常無法使用 (0 * TimeInterval_Second, 60 * TimeInterval_Second) 範圍中的樣本。 同樣地,您可以使用 GetSample() 的百分比參數來強制特定樣本百分比需求。

重要

我們強烈建議您避免「只」GetSample(1)依賴自動調整公式中的。 這是因為 GetSample(1) 基本上對 Batch 服務說,「給我最後一個範例,無論你多久前擷取它。因為它只是單一範例,而且可能是較舊的範例,所以它可能不會代表最近工作或資源狀態的大圖。 如果您使用 GetSample(1),請確定它是較大的陳述式,而且不是您的公式所依賴的唯一資料點。

撰寫自動調整公式

您建置自動調整公式的方式是使用上述元件撰寫陳述式,再將這些陳述式結合成完整的公式。 在本節中,您會建立可執行真實世界調整決策和進行調整的範例自動調整公式。

首先,讓我們定義新自動調整公式的需求。 公式應該︰

  • 如果 CPU 使用率偏高,則增加集區中專用計算節點的目標數目。
  • 如果 CPU 使用率偏低,則減少集區中專用計算節點的目標數目。
  • 一律以 400 為專用節點的數目上限。
  • 減少節點數目時,請勿移除正在執行工作的節點;如有必要,請等候工作完成,再移除節點。

公式中的第一個陳述式會在高 CPU 使用量期間增加節點數目。 您將陳述式定義為在使用者定義的變數 ($totalDedicatedNodes) 中填入 110% 的專用節點目前目標數目值,但僅限在過去 10 分鐘期間平均 CPU 使用率下限大於 70%。 否則,使用目前的專用節點數目值。

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

為了減少低 CPU 使用率期間的專用節點數目,如果在過去 60 分鐘內平均 CPU 使用率低於 20%,公式中的下一個陳述式會將相同的 $totalDedicatedNodes 變數設定為 90% 的專用節點目前目標數目。 否則,使用在上述陳述式中填入的目前 $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;

注意

如果您選擇的話,可以在公式字串中包含註解和分行符號。 另請注意,遺漏分號可能會導致評估錯誤。

自動調整間隔

依預設,Batch 服務會根據其自動調整公式每隔 15 分鐘調整集區的大小。 可使用下列的集區屬性設定此間隔:

最小間隔為 5 分鐘,而最大間隔為 168 小時。 如果指定此範圍以外的時間間隔,則 Batch 服務會傳回「不正確的要求 (400)」錯誤。

注意

自動調整目前不適合作為低於一分鐘的變更回應,而是要在您執行工作負載時逐步調整您的集區大小。

使用 Batch SDK 建立已啟用自動調整的集區

Batch SDKBatch REST APIBatch PowerShell CmdletBatch CLI 都可用來設定集區自動調整。 在本節中,您會看到 .NET 和 Python 的範例。

.NET

若要在 .NET 中建立已啟用自動調整的集區,請遵循下列步驟:

  1. 使用 BatchClient.PoolOperations.CreatePool 建立集區。
  2. CloudPool.AutoScaleEnabled 屬性設定為 true
  3. 使用自動調整公式來設定 CloudPool.AutoScaleFormula 屬性。
  4. (選擇性) 設定 CloudPool.AutoScaleEvaluationInterval 屬性 (預設值為 15 分鐘)。
  5. 使用 CloudPool.CommitCommitAsync 認可集區。

下列範例在 .NET 中建立已啟用自動調整的集區。 集區的自動調整公式會將星期一的專用節點目標數目設定為 5,而將一週其他各天的節點目標數目設定為 1。 自動調整間隔 設定為 30 分鐘。 在此程式碼片段及本文的其他 C# 程式碼片段中,myBatchClientBatchClient 類別適當初始化的執行個體。

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

重要

當您建立已啟用自動調整的集區時,請勿在對 CreatePool 的呼叫上指定 targetDedicatedNodes 參數或 targetLowPriorityNodes 參數。 請改為指定集區上的 AutoScaleEnabledAutoScaleFormula 屬性。 這些屬性的值會判斷每個節點類型的目標數目。

若要對已啟用自動調整的集區手動調整大小 (例如使用 BatchClient.PoolOperations.ResizePoolAsync),您必須先在集區停用自動調整,再調整其大小。

提示

如需使用 .NET SDK 的更多範例,請參閱 GitHub 上的 Batch .NET 快速入門存放庫

Python

若要使用 Python SDK 建立已啟用自動調整功能的集區:

  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)

提示

如需更多使用 Python SDK 的範例,請參閱 GitHub 上的 Batch Python 快速入門存放庫

在現有集區啟用自動調整

每個 Batch SDK 都會提供啟用自動調整的方法。 例如:

當您在現有集區啟用自動調整時,請記住:

  • 如果目前已在集區上停用自動調整,您必須在發出要求時指定有效的自動調整公式。 您可以選擇性地指定自動調整間隔。 如果您未指定間隔,則會使用預設值 15 分鐘。
  • 如果目前已在集區上啟用自動調整,您可以指定新的公式、新的間隔或兩者。 您必須至少指定其中一個屬性。
    • 如果您指定新的自動調整間隔,則會停止現有的排程並啟動新的排程。 新排程的開始時間是發出啟用自動調整要求的時間。
    • 如果您省略自動調整公式或間隔,則 Batch 服務會繼續使用該設定目前的值。

注意

如果當您在 .NET 中建立集區時,指定 CreatePool 方法之 targetDedicatedNodestargetLowPriorityNodes 參數的值,或在其他語言中指定相當的參數,則在評估自動調整公式時會略過這些值。

此 C# 範例使用 Batch .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);

更新自動調整間隔

若要更新現有已啟用自動調整集區的自動調整評估間隔,呼叫作業以使用新的間隔再次啟用自動調整。 例如,若要針對在 .NET 中已啟用自動調整的集區,將自動調整評估間隔設定為 60 分鐘︰

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

評估自動調整公式

您可以先評估公式,再將它套用至集區。 這可讓您先測試公式的結果,再將其放入生產環境。

您必須先使用有效的公式在集區上啟用自動調整,例如單行公式 $TargetDedicatedNodes = 0,才能評估自動調整公式。 然後,使用下列其中之一來評估您想要測試的公式︰

以下 Batch .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

取得自動調整執行的相關資訊

建議您定期檢查 Batch 服務的自動調整公式評估。 若要這麼做,請取得 (或重新整理) 集區的參考,然後檢查其上次自動調整執行的內容。

在 Batch .NET 中,CloudPool.AutoScaleRun 屬性有數個屬性,可提供最近在集區上執行之自動調整的相關資訊:

在 REST API 中,取得集區的相關資訊要求會傳回集區的相關資訊,其中包含 autoScaleRun 屬性中最近執行的自動調整資訊。

下列 C# 範例會使用 Batch .NET 程式庫來列印集區 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);

前述範例的輸出範例為:

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,以檢查自動調整歷程記錄。 Batch 發出此事件,以記錄每次出現的自動調整公式評估和執行,這有助於針對潛在問題進行疑難排解。

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 - 下午 6: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); 表示美加山區日光節約時間 (MDT)。 請記住,在日光節約時間開始和結束時,必須調整時差 (如果適用)。

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

下一步