分享方式:


Durable Functions 疑難排解指南

Durable Functions 是 Azure Functions 的延伸模組,可讓您使用一般程式碼建置無伺服器協調流程。 如需 Durable Functions 的詳細資訊,請參閱 Durable Functions 概觀

本文中的指引協助您針對 Durable Functions 應用程式中的常見案例進行疑難排解。

注意

您可以要求 Microsoft 支援工程師協助診斷您的應用程式問題。 如果您無法使用本指南診斷您的問題,可以在 Azure 入口網站中透過您函數應用程式的 [支援 + 疑難排解] 區段,存取 [新的支援要求] 刀鋒視窗以提交支援要求。

Screenshot of support request page in Azure Portal.

提示

偵錯和診斷問題時,建議您先確定應用程式使用的是最新版的 Durable Functions 延伸模組。 在大部分情況下,使用最新版本可減輕其他使用者已經回報的已知問題。 如需升級延伸模組版本的指示,請參閱升級 Durable Functions 延伸模組版本一文。

在 Azure 入口網站中,[診斷和解決問題] 索引標籤是監視和診斷應用程式相關問題的實用資源。 它也會根據診斷結果,為您的問題提供可能的解決方案。 如需詳細資訊,請參閱 Azure 函數應用程式診斷

如果上述資源無法解決問題,下列各節可針對特定應用程式徵兆提供建議:

協調流程停滯在 Pending 狀態

當您啟動協調流程時,會將「啟動」訊息寫入 Durable 延伸模組管理的內部佇列,而協調流程的狀態則會設定為「擱置」。 當可用的應用程式執行個體挑選並成功處理協調流程訊息之後,狀態會轉換為「執行中」(或某些其他非「擱置」狀態)。

使用下列步驟,針對無限期停滯在「擱置」狀態的協調流程執行個體進行疑難排解。

  • 檢查持久工作架構追蹤是否有受影響協調流程執行個體識別碼的警告或錯誤。 您可以在追蹤錯誤/警告一節中找到範例查詢。

  • 請檢查指派給停滯協調器的 Azure 儲存體控制佇列,以查看其「啟動訊息」是否仍然存在。如需控制佇列的詳細資訊,請參閱 Azure 儲存體提供者控制佇列文件

  • 將應用程式的平台設定版本變更為「64 位元」。 有時,協調流程會因應用程式記憶體不足而無法啟動。 切換至 64 位元流程可讓應用程式配置更多的記憶體總量。 這只適用於 App Service 基本、標準、進階和和彈性進階方案。 免費或使用量方案支援 64 位元流程。

協調流程在長時間延遲之後啟動

一般而言,協調流程會在排程後的幾秒內啟動。 不過,在某些情況下,協調流程可能需要較長的時間才能啟動。 使用下列步驟,在協調流程需要幾秒鐘以上的時間才能開始執行時進行疑難排解。

協調流程未完成/停滯於 Running 狀態

如果協調流程長時間維持在「執行中」狀態,通常表示它正在等候已排定的長時間執行工作完成。 例如,它可能正在等待持久計時器工作、活動工作或外部事件工作完成。 不過,如果您觀察到排程的工作已順利完成,但協調流程卻仍然沒有任何進展,則可能發生問題,導致協調流程無法繼續下一項工作。 我們通常將此狀態的協調流程稱為「停滯的協調流程」。

請使用下列步驟對停滯的協調流程進行疑難排解:

  • 嘗試重新啟動函數應用程式。 如果協調流程因應用程式或延伸模組程式碼的暫時性錯誤或死結而停滯,則可採用此步驟。

  • 檢查 Azure 儲存體帳戶控制佇列,以查看是否有任何佇列持續成長。 這個 Azure 儲存體傳訊 KQL 查詢可協助找出清除協調流程佇列訊息的問題。 如果問題只影響單一控制佇列,則可能表示只有特定應用程式執行個體發生問題,在此情況下,擴大或縮減規模以移出狀況不良的 VM 執行個體可能會有所幫助。

  • 使用 Azure 儲存體傳訊一節中的 Application Insights 查詢,使用該佇列名稱作為分割區識別碼進行篩選,並尋找與該控制佇列分割相關的任何問題。

  • 檢查 Durable Functions 最佳做法和診斷工具中提供的指引。 某些問題可能是由已知的 Durable Functions 反向模式造成。

  • 檢查 Durable Functions 版本設定文件。 某些問題可能是因為傳輸中協調流程執行個體的中斷性變更所造成。

協調流程執行速度緩慢

大量資料處理、內部錯誤和計算資源不足都可能會導致協調流程的執行速度比正常慢。 使用下列步驟,針對執行時間超過預期的協調流程進行疑難排解:

  • 檢查持久工作架構追蹤是否有受影響協調流程執行個體識別碼的警告或錯誤。 您可以在追蹤錯誤/警告一節中找到範例查詢。

  • 如果您的應用程式使用 .NET 內含式模型,請考慮啟用延長工作階段。 延長工作階段可將歷程記錄載入降到最低,這可能會降低處理速度。

  • 檢查效能和可擴縮性瓶頸。 應用程式效能取決於諸多因素。 例如,高 CPU 使用量或大量記憶體使用量可能會導致延遲。 如需詳細指引,請參閱 Durable Functions 的效能和規模

範例查詢

本節說明如何在 Azure Functions 應用程式設定的 Azure Application Insights 執行個體中撰寫自訂 KQL 查詢,以針對問題進行疑難排解。

Azure 儲存體傳訊

使用預設的 Azure 儲存體提供者時,所有 Durable Functions 行為都是由 Azure 儲存體佇列訊息所驅動,且與協調流程相關的所有狀態都儲存在表格儲存體和 Blob 儲存體中。 啟用持久工作架構追蹤時,所有 Azure 儲存體互動都會記錄至 Application Insights,且此資料在偵錯執行和效能問題時非常重要。

從 Durable Functions 延伸模組的 v2.3.0 開始,您可以在 host.json 檔案中更新記錄設定,將這些持久工作架構記錄發佈至 Application Insights 執行個體。 如需作法的相關資訊和指示,請參閱持久工作架構記錄一文

下列查詢用來檢查特定協調流程執行個體的端對端 Azure 儲存體互動。 編輯 startorchestrationInstanceID,依照時間範圍和執行個體識別碼進行篩選。

let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this 
let orchestrationInstanceID = "XXXXXXX"; //edit this
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = customDimensions["prop__PartitionId"] 
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
| where instanceId == orchestrationInstanceID
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

追蹤錯誤/警告

下列查詢會搜尋指定協調流程執行個體的錯誤和警告。 您必須為 orchestrationInstanceID 提供值。

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); 
traces  
| where timestamp > start and timestamp < start + 1h
| extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] ) 
| extend logLevel = customDimensions["LogLevel"]
| extend functionName = customDimensions["prop__functionName"]
| extend status = customDimensions["prop__status"]
| extend details = customDimensions["prop__Details"] 
| extend reason = customDimensions["prop__reason"]
| where severityLevel > 1 // to see all logs of  severity level "Information" or greater.
| where instanceId == orchestrationInstanceID
| sort by timestamp asc 

控制佇列/分割區識別碼記錄

下列查詢會搜尋與 instanceId 控制佇列相關聯的所有活動。 您必須在 orchestrationInstanceID 中提供 instanceID 的值,並在 start 中提供查詢的開始時間。

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this
traces  // determine control queue for this orchestrator
| where timestamp > start and timestamp < start + 1h 
| extend instanceId = customDimensions["prop__TargetInstanceId"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| where partitionId contains "control" 
| where instanceId == orchestrationInstanceID
| join kind = rightsemi(
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
) on partitionId
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Application Insights 資料行參考

以下是上述查詢及其各自描述所投影的資料行清單。

資料行 描述
pid 函數應用程式執行個體的處理序識別碼。 這對於判斷協調流程執行時是否回收處理序很有幫助。
taskName 記錄事件的名稱。
eventType 訊息的型別,這通常代表協調器執行的工作。 如需可能值及其描述的完整清單,請參閱這裡
extendedSession 布林值,指出是否已啟用延長工作階段
account 應用程式使用的儲存體帳戶。
詳細資料 特定事件的其他資訊 (如果有的話)。
instanceId 指定協調流程或實體執行個體的識別碼。
messageId 指定佇列訊息的唯一 Azure 儲存體識別碼。 此值最常出現在 ReceivedMessage、ProcessingMessage 和 DeletingMessage 追蹤事件中。 請注意,此值不會出現在 SendingMessage 事件中,因為訊息識別碼是在我們傳送訊息之後由 Azure 儲存體產生。
executionId 協調器執行識別碼,只要叫用 continue-as-new,此識別碼即會變更。
年齡 訊息加入佇列後的毫秒數。 數字很大通常表示發生效能問題。 例外狀況是 TimerFired 訊息類型,會視計時器的持續時間而可能有較大的 Age 值。
latencyMs 某些儲存體作業所花費的毫秒數。
dequeueCount 訊息已從佇列清除的次數。 在正常情況下,此值一律為 1。 如果超過一,則可能有問題。
partitionId 與此記錄相關聯的佇列名稱。
totalEventCount 目前動作所涉及的歷程記錄事件數目。
taskHub 工作中樞的名稱。
newEvents 歷程記錄事件的逗號分隔清單,這些事件會寫入儲存體中的歷程記錄資料表。