Durable Functions トラブルシューティング ガイド

この記事は、Durable Functions アプリの一般的なシナリオのトラブルシューティングに役立ちます。 次の一覧で症状を見つけ、リンクされた手順に従って問題を診断して解決します。

一般的な症状

Application Insights で実行できる KQL 診断クエリについては、Durable Functions診断用の Sample KQL クエリを参照してください。

オーケストレーションが Pending 状態で停止する

オーケストレーションを開始すると、Durable 拡張機能によって管理される内部キューに "開始" メッセージが書き込まれ、オーケストレーションの状態が "保留中" に設定されます。 使用可能なアプリ インスタンスがオーケストレーション メッセージを取得して正常に処理すると、状態は "実行中" (または他の "保留中ではない" 状態) に遷移します。

"保留中" 状態で無期限にスタックしたままのオーケストレーション インスタンスをトラブルシューティングするには、次の手順に従います。

  1. Durable Task Framework トレースで、影響を受けるオーケストレーション インスタンス ID の警告またはエラーを確認します。 Application Insights の トレース エラーと警告クエリ を使用して、インスタンスに関連するエラーを検索します。

  2. Azure Storage コントロール キューを調べて、オーケストレーションの "開始メッセージ" がまだキュー内にあるかどうかを確認します。 Azure ポータルで、ストレージ アカウントに移動し、Queues を選択し、control プレフィックスを持つキューを探します。 制御キューのしくみの背景については、Azure Storage プロバイダーコントロール キューのドキュメントを参照してください。

  3. アプリの プラットフォーム構成64 ビットに変更します。 アプリがメモリ不足のため、オーケストレーションの開始に失敗することがあります。 64 ビット プロセスに切り替えると、アプリはより多くの合計メモリを割り当てることができます。 この変更は、App Service Basic、Standard、Premium、Elastic Premium のプランにのみ適用されます。 Free プランまたは従量課金プランでは、64 ビット プロセスはサポート されていません

オーケストレーションは長い遅延後に開始されます

通常、オーケストレーションはスケジュールされてから数秒以内に開始されます。 ただし、特定のケースではオーケストレーションの開始に時間がかかる場合があります。 オーケストレーションの実行を開始するのに数秒以上かかる場合のトラブルシューティングを行うには、次の手順に従います。

  1. 遅延が、パーティションの再調整やタイマーベースのポーリング間隔などのAzure Storage プロバイダーの既知の制限と一致するかどうかを確認してください。

  2. Durable Task Framework トレースで、影響を受けるオーケストレーション インスタンス ID の警告またはエラーを確認します。 Application Insights の トレース エラーと警告クエリ を使用して、インスタンスに関連するエラーを検索します。

オーケストレーションが Running 状態で停止する

オーケストレーションの状態が予想以上に長く "実行中" と表示されている場合、または進行状況が停止しているように見える場合、オーケストレーションは完了していないタスクを待機している可能性があります。 たとえば、持続的タイマー、アクティビティ タスク、または外部イベントを待機している可能性があります。 スケジュールされたタスクが正常に完了してもオーケストレーションが進まない場合は、問題が発生して次の手順に進めなくなる可能性があります。 この状態のオーケストレーションは、多くの場合、"スタック オーケストレーション" と呼ばれます。

スタックオーケストレーションのトラブルシューティングを行うには、次の手順に従います。

  1. 関数アプリを再起動してみてください。 この手順は、アプリまたは拡張コードの一時的なバグまたはデッドロックが原因でオーケストレーションがスタックした場合に役立ちます。

  2. Azure Storage アカウント制御キューを調べて、キューが継続的に増加しているかどうかを確認します。 Application Insights の Azure Storage メッセージング クエリを使用して、オーケストレーション メッセージのデキューに関する問題を特定します。 問題が 1 つの制御キューにのみ影響する場合は、特定のアプリ インスタンスの問題を示している可能性があります。 その場合は、スケールアップまたはスケールダウンして、異常な VM インスタンスから移動すると役立つ可能性があります。

  3. Azure Storage メッセージング クエリ結果をパーティション ID としてキュー名でフィルター処理し、その特定の制御キュー パーティションに関連する問題を探します。

  4. Durable Functionsバージョン管理のドキュメントを確認してください。 インフライト オーケストレーション インスタンスに重大な変更が加えられると、オーケストレーションがスタックする可能性があります。

オーケストレーションの完了に予想以上に時間がかかる

大量のデータ処理、内部エラー、十分なコンピューティング リソースが原因で、オーケストレーションの実行速度が通常よりも遅くなる可能性があります。 予想以上に完了するまでに時間がかかるオーケストレーションのトラブルシューティングを行うには、次の手順に従います。

  1. Durable Task Framework トレースで、影響を受けたオーケストレーション インスタンス ID の警告またはエラーを確認します。 Application Insights の トレース エラーと警告クエリ を使用して、インスタンスに関連するエラーを検索します。

  2. アプリで .NET インプロセス モデルを使用する場合は、拡張セッションを有効にすることを検討してください。 拡張セッションは履歴の負荷を最小限に抑え、処理が遅くなる可能性があります。

  3. パフォーマンスとスケーラビリティのボトルネックを確認します。 CPU 使用率が高い、またはメモリ消費量が大きいと、遅延が発生する可能性があります。 詳細なガイダンスについては、Durable Functions におけるパフォーマンスとスケールを参照してください。

Durable Functions 診断の KQL クエリのサンプル

Azure Functions アプリ用に構成された Azure アプリケーション Insights インスタンスにカスタム KQL クエリを記述して、問題のトラブルシューティングを行います。 これらのクエリで使用される列定義については、列の リファレンスを参照してください

Azure Storage メッセージング

既定のAzure Storage プロバイダーを使用すると、すべてのDurable Functions動作はAzure Storageキュー メッセージによって駆動され、オーケストレーションに関連するすべての状態がテーブル ストレージと BLOB ストレージに格納されます。 Durable Task Framework トレースを有効にすると、すべてのAzure Storage操作が Application Insights に記録されます。 このデータは、実行とパフォーマンスの問題をデバッグするために非常に重要です。

Durable Functions拡張機能の v2.3.0 以降では、host.json ファイルのログ構成を更新することで、これらの Durable Task Framework ログを Application Insights インスタンスに発行できます。 詳細については、 Durable Task Framework のログ記録に関する記事を参照してください。

次のクエリでは、特定のオーケストレーション インスタンスに対するエンド ツー エンドのAzure Storage操作を検査します。 startorchestrationInstanceIDを編集して、時間範囲とインスタンス ID でフィルター処理します。

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 

キューとパーティション ID のログを制御する

次のクエリでは、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

Durable Functions クエリ用 Application Insights 列参照

次の表に、前のクエリによって予測される列とその説明を示します。

コラム 説明
pid 関数アプリ インスタンスのプロセス ID。 この値は、オーケストレーションの実行中にプロセスがリサイクルされたかどうかを確認するのに役立ちます。
taskName ログに記録されるイベントの名前。
eventType 通常、オーケストレーターによって実行される作業を表すメッセージの種類。 使用可能な値とその説明の完全な一覧については、EventType.csを参照してください。
拡張セッション 拡張セッションが有効かどうかを示すブール値。
アカウント アプリによって使用されるストレージ アカウント。
details 特定のイベントに関する追加情報 (使用可能な場合)。
instanceId 特定のオーケストレーションまたはエンティティ インスタンスの ID。
メッセージID 特定のキュー メッセージの一意のAzure Storage ID。 この値は、最も一般的に ReceivedMessage、ProcessingMessage、および DeletingMessage トレース イベントに表示されます。 この値は SendingMessage イベントには存在しません。メッセージ ID はメッセージが送信Azure Storage によって生成されるためです。
エグゼキューションID (executionId) オーケストレーター実行の ID。 continue-as-new が呼び出されるたびに変更されます。
年齢 メッセージがエンキューされてからのミリ秒数。 多くの場合、大きな数値はパフォーマンスの問題を示します。 例外は TimerFired メッセージの種類で、タイマーの期間に応じて Age 値が大きくなる可能性があります。
latencyMs ストレージ操作に要するミリ秒数。
dequeueCount メッセージがデキューされる回数。 通常の状況では、この値は常に 1 です。 複数の場合は、問題が発生している可能性があります。
partitionId このログに関連付けられているキューの名前。
トータルイベントカウント 現在のアクションに関係する履歴イベントの数。
タスクハブ タスク ハブの名前。
新しいイベント ストレージ内の履歴テーブルに書き込まれる履歴イベントのコンマ区切りのリスト。

従量課金プランでの接続管理の問題

Azure Functions従量課金プランで実行されているアプリには、接続の制限が適用されます。 一般的な症状は次のとおりです。

  • アクティビティ関数または外部サービスを呼び出すときの断続的な接続エラー。
  • 負荷の下で散発的に失敗するオーケストレーション。
  • ログ内のソケット不足エラー。

接続の使用量を減らすには、すべての関数呼び出しで新しいHttpClientFactory インスタンスを作成する代わりに、HttpClientまたは共有静的クライアントを使用します。 接続プールとベスト プラクティスの詳細なガイダンスについては、「manage connections in Azure Functions」を参照してください。

一般的なヒント

ヒント

特定のトラブルシューティング手順に進む前に、アプリで最新のDurable Functions拡張機能バージョンを使用していることを確認してください。 ほとんどの場合、最新バージョンを使用すると、他のユーザーによって既に報告されている既知の問題が軽減されます。 アップグレード方法については、「Upgrade Durable Functions拡張機能のバージョンを参照してください。

Azure ポータルの Diagnose と問題の解決 タブは、アプリケーションに関連する問題の監視と診断に役立ち、潜在的な解決策を提案するのに役立ちます。 詳細については、「Azure Function app diagnostics」を参照してください。

Durable Functionsの問題のサポートを受ける

このガイドを使用して問題を解決できない場合は、Azure ポータルの関数アプリ ページの Support + troubleshooting セクションで New サポート 要求 ブレードを開いてサポート チケットを提出できます。

Azure portal のサポート要求ページのスクリーンショット

質問とコミュニティサポートについては、次のいずれかのGitHubリポジトリで問題を開きます。 バグを報告するときは、影響を受けるインスタンス ID、問題を示す UTC の時間範囲、アプリケーション名 (可能な場合)、展開リージョンなどの情報を含めて調査を高速化します。