簡體   English   中英

在 Azure Durable Functions 中,如何適當地確定大量並行活動的進展?

[英]In Azure Durable Functions, how do I appropriately determine the progression of a large number of parallel activities?

我編寫了一個 Durable Function Orchestrator 函數,其主要工作是扇出平均 1,000 個並行活動。 由於這些活動的完成是前端用戶在技術上會等待的事情,我希望能夠在活動仍在運行時查詢進度(在前端顯示進度條)。

以下是當前編排器代碼的一部分,但我懷疑它是否符合編排器功能的約束( https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable -functions-checkpointing-and-replay#orchestrator-code-constraints )。

基本上,如果 DF 框架在每次等待之前重放編排器,這感覺就像等待它處理的等待次數不合理:

var replicationTasks = new List<Task<ReplicationOutput>>();
var replicationResults = new List<ReplicationOutput>();
// start up each simulation
for (int i = 0; i < inputs.NumberOfReplications; i++)
{
    var replicationInput = new ReplicationInput();
    var task = context.CallActivityAsync<ReplicationOutput>("SimulationOrchestrator_SimulateReplication", replicationInput);
    replicationTasks.Add(task);
}
// set initial custom status 
var progress = new Progress();
progress.NumberCompleted = 0;
progress.Total = inputs.NumberOfReplications;
progress.TimeStarted = context.CurrentUtcDateTime;
progress.ElapsedTime = context.CurrentUtcDateTime.Subtract(progress.TimeStarted);
context.SetCustomStatus(progress);

// as each task finishes
while (replicationTasks.Any())
{
    Task<ReplicationOutput> nextFinished = await Task.WhenAny(replicationTasks);

    replicationTasks.Remove(nextFinished);
    replicationResults.Add(await nextFinished);

    // update progress object and custom status
    progress.NumberCompleted++;
    progress.ElapsedTime = context.CurrentUtcDateTime.Subtract(progress.TimeStarted);
    context.SetCustomStatus(progress);
}
// aggregate replications together into a single set of results
return new Results(replicationResults);

這在簡單的測試條件下不一定會失敗,但協調器文檔警告(相當積極地)保持歷史表清晰,避免等待/阻塞等。

是否有記錄或“最佳實踐”方法來實現可查詢進度的目標? 我見過的所有扇出/扇入示例await Task.WhenAll(replicationTasks)使用await Task.WhenAll(replicationTasks)所有任務完成后才繼續,我認為這不會允許增量進度檢查。

您似乎在這里有兩個問題:

大量動作導致重放次數過多

眾所周知,持久函數在必須重放大量操作時會降低性能。 在 Durable Functions 的 .NET 運行時中,DF 會在 100,000 個操作 ( Github ) ( StackOverflow ) 后自動中止。 這個 100k 限制是可配置的,但它代表了我找到的關於“DF 打算處理多少操作”的唯一准則。

我還沒有在網上看到有人討論過減少每個 Durable Function 負責的操作數量的架構。 我有您描述的相同用例(並發受限的扇出),我找到了幾個選項:

  1. 使用continueAsNew DF API 調用定期重新啟動編排器,並使用新的空重播歷史記錄。 該調用采用一個參數,您可以在其中傳遞您希望 DF 的新實例具有的任何狀態(即,其余的工作負載)。 它與函數遞歸中的概念相同,只是使用 DF。 這是一種相對簡單的方法,可以直接解決重放性能問題,而無需在架構中引入新組件。 代價是您的處理周期性地停止,而您避免產生新的活動以准備重新啟動 Orchestrator。

  2. 您可以限制過多的重播批處理任務,並有一個單獨的 DF 層來處理批處理任務。 這使您的頂級 Orchestrator 負責 1/n 的操作,其中 n 是批處理大小。 我覺得這是一個笨拙的解決方案,它限制了頂級 DF 可以監督扇出的粒度,但它解決了重放問題。

  3. 您可以使用 Extended Sessions 來延遲 Durable Functions 在調用操作后關閉一段時間。 如果您的 DF 在此期間被激活,它將繼續執行而不會重播,就好像它只是一個普通的程序在做它的事情。 您將支付讓它一直運行的成本,但如果它有大量的重放歷史,它可能會經常醒來,以至於額外的執行成本可以忽略不計。

  4. 如果您不需要對並發和任務調度進行細粒度控制,您可以考慮讓 Orchestrator 將任務推送到存儲隊列,讓隊列消息觸發普通函數。 然后,您的 DF 可以在將任務數據移交給隊列后立即結束其生命周期。 如果它需要處理任務輸出,它可以等待恢復處理,直到另一個函數發送一個事件通知它所有任務都已處理。

查詢你的 DF 進度

Durable Functions 有一個明確的機制來向感興趣的各方傳達他們的進展。 或者,您的 Orchestrator 可以將其進度保存在其他各方可以訪問的地方。

您的第一個選擇是使用 Durable Function 的自定義狀態功能。 您可以定期更新 Durable Function 的狀態以反映其進度,並查詢 DF 的進度

另一種選擇是持久實體; 它們是 DF 存儲在 DF 的上下文和生命周期之外持續存在的數據的一種便捷方式,而且至關重要的是,DF 函數應用程序內的客戶端函數可以讀取 DF 寫入的持久實體。 圍繞它和bam包裝一個 HTTP 觸發器,你有進度查詢。

最后,通常通過將進度寫入任何主要數據庫並從輪詢 HTTP 端點中的數據庫讀回來處理此任務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM