Durable Functionsは Azure Functions の拡張機能であり、通常のコードを使用してサーバーレス オーケストレーションを構築できます。 Durable Functionsの詳細については、「Durable Functionsの概要を参照してください。
この記事は、Durable Functions アプリの一般的なシナリオのトラブルシューティングに役立ちます。
注
Microsoft サポート エンジニアは、アプリケーションに関する問題の診断に役立ちます。 このガイドを使用して問題を診断できない場合は、Azure ポータルの関数アプリ ページの サポートとトラブルシューティング セクションで 新しいサポート要求 ブレードを開いて、サポート チケットを提出してください。
ヒント
問題のデバッグと診断を行うときは、まず、アプリで最新のDurable Functions拡張機能バージョンが使用されていることを確認することをお勧めします。 ほとんどの場合、最新バージョンを使用すると、他のユーザーによって既に報告されている既知の問題が軽減されます。 拡張機能のバージョンをアップグレードする方法については、「Upgrade Durable Functions拡張機能のバージョンを参照してください。
Azure ポータルの Diagnose and solve problems タブは、アプリケーションに関連する可能性のある問題を監視および診断するのに役立つリソースです。 また、診断に基づいて問題に対する潜在的な解決策も提供します。 詳細については、「Azure Function app diagnostics」を参照してください。
前のリソースで問題が解決しなかった場合は、次のセクションで特定のアプリケーションの症状に関するアドバイスを提供します。
オーケストレーションが Pending 状態で停止する
オーケストレーションを開始すると、Durable 拡張機能によって管理される内部キューに "開始" メッセージが書き込まれ、オーケストレーションの状態が "保留中" に設定されます。 使用可能なアプリ インスタンスがオーケストレーション メッセージを取得して正常に処理すると、状態は "実行中" (または他の "保留中ではない" 状態) に遷移します。
"保留中" 状態で無期限にスタックしたままのオーケストレーション インスタンスをトラブルシューティングするには、次の手順に従います。
Durable Task Framework トレースで、影響を受けるオーケストレーション インスタンス ID の警告またはエラーを確認します。 [トレース エラー/警告] セクションでサンプル クエリを見つけます。
スタック オーケストレーターに割り当てられている Azure Storage コントロール キューを調べて、その "開始メッセージ" がまだ存在するかどうかを確認します。 制御キューの詳細については、Azure Storage プロバイダー制御キューのドキュメントを参照してください。
アプリの プラットフォーム構成 バージョンを "64 ビット" に変更します。 アプリのメモリ不足が原因でオーケストレーションが開始されない場合があります。 64 ビット プロセスに切り替えると、アプリはより多くの合計メモリを割り当てることができます。 この変更は、App Service Basic、Standard、Premium、Elastic Premium のプランにのみ適用されます。 Free プランまたは従量課金プランでは、64 ビット プロセスはサポート されていません 。
オーケストレーションは長い遅延後に開始されます
通常、オーケストレーションはスケジュールされてから数秒以内に開始されます。 ただし、特定のケースではオーケストレーションの開始に時間がかかる場合があります。 オーケストレーションの実行を開始するのに数秒以上かかる場合のトラブルシューティングを行うには、次の手順に従います。
Azure Storage の遅延オーケストレーションに関するドキュメントを参照して、遅延が既知の制限によって引き起こされているかどうかを確認してください。
Durable Task Framework トレースで、影響を受けるオーケストレーション インスタンス ID の警告またはエラーを確認します。 [トレース エラー/警告] セクションでサンプル クエリを見つけます。
オーケストレーションが完了しないか、Running 状態で停止している
オーケストレーションが長時間 "実行中" 状態のままである場合は、通常、実行時間の長いタスクの完了を待機していることを意味します。 たとえば、持続的タイマー タスク、アクティビティ タスク、または外部イベント タスクの完了を待機している可能性があります。 スケジュールされたタスクが正常に完了したが、オーケストレーションがまだ進行していない場合は、オーケストレーションが次のタスクに進まないという問題が発生している可能性があります。 この状態のオーケストレーションは、多くの場合、"スタック オーケストレーション" と呼ばれます。
スタックオーケストレーションのトラブルシューティングを行うには、次の手順に従います。
関数アプリを再起動してみてください。 この手順は、アプリまたは拡張コードの一時的なバグまたはデッドロックが原因でオーケストレーションがスタックした場合に役立ちます。
Azure Storage アカウント制御キューを調べて、キューが継続的に増加しているかどうかを確認します。 このAzure Storageメッセージング KQL クエリは、オーケストレーション メッセージのデキューに関する問題を特定するのに役立ちます。 問題が 1 つの制御キューにのみ影響する場合は、特定のアプリ インスタンスにのみ存在する問題を示している可能性があります。その場合、スケールアップまたはスケールダウンして異常な VM インスタンスから移動すると役立ちます。
Azure Storage メッセージング セクション の Application Insights クエリを使用して、そのキュー名をパーティション ID としてフィルター処理し、その制御キュー パーティションに関連する問題を探します。
Durable Functionsバージョン管理のドキュメントを確認してください。 一部の問題は、インフライト オーケストレーション インスタンスの重大な変更によって発生する可能性があります。
オーケストレーションの実行速度が遅い
大量のデータ処理、内部エラー、十分なコンピューティング リソースが原因で、オーケストレーションの実行速度が通常よりも遅くなる可能性があります。 実行に予想以上に時間がかかるオーケストレーションのトラブルシューティングを行うには、次の手順に従います。
Durable Task Framework トレースで、影響を受けたオーケストレーション インスタンス ID の警告またはエラーを確認します。 サンプル クエリは、 トレース エラー/警告セクションにあります。
アプリで .NET インプロセス モデルを使用する場合は、拡張セッションを有効にすることを検討してください。 拡張セッションは履歴の負荷を最小限に抑え、処理が遅くなる可能性があります。
パフォーマンスとスケーラビリティのボトルネックを確認します。 アプリケーションのパフォーマンスは、多くの要因によって異なります。 たとえば、CPU 使用率が高い場合やメモリ消費量が多い場合は、遅延が発生する可能性があります。 詳細なガイダンスについては、Durable Functions におけるパフォーマンスとスケールを参照してください。
サンプル クエリ
Azure Functions アプリ用に構成された Azure Application 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操作を検査します。
startとorchestrationInstanceIDを編集して、時間範囲とインスタンス 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
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従量課金プランで実行されているアプリは、接続制限の対象となります。 接続が使い果たされたために断続的に失敗する接続エラーまたはオーケストレーションが発生した場合は、接続プールのガイダンスと接続の使用量を減らすためのベスト プラクティスについては>
サポートの利用
質問とサポートについては、次のいずれかのGitHub リポジトリで問題を開きます。 Azureのバグを報告するときは、影響を受けるインスタンス ID、問題を示す UTC の時間範囲、アプリケーション名 (可能な場合)、デプロイ リージョンなどの情報を含めて、調査を大幅に高速化します。
- Durable Functions拡張機能と.NET インプロセスSDK
- .NETアイソレーテッド SDK
- Durable Functions for Java
- Durable Functions for JavaScript
- Python の Durable Functions