Troubleshooting and Debugging Tips - AWS Flow Framework for Java

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Troubleshooting and Debugging Tips

このセクションでは、 AWS Flow Framework for Java を使用してワークフローを開発する際に実行する可能性のある一般的な落とし穴について説明します。また、問題の診断とデバッグに役立つヒントも紹介します。

コンパイルエラー

AspectJ のコンパイル時ウィービングオプションを使用している場合、コンパイラでワークフローおよびアクティビティ用に生成されたクライアントクラスを発見できないコンパイル時エラーが発生する場合があります。このようなコンパイルエラーは、コンパイル時に生成されたクライアントを AspectJ ビルダーが無視したことが原因です。この問題を解決するには、AspectJ の機能をプロジェクトから削除して再度有効にします。この操作は、ワークフローまたはアクティビティのインターフェイスが変更される度に行う必要があります。この問題を回避するために、ロード時間ウィービングオプションを使用することをお勧めします。詳細については、「AWS Flow Framework for Java のセットアップ」セクションを参照してください。

不明なリソース障害

使用できないリソースに対して操作を実行しようとすると、Amazon SWF より未知のリソース障害が返ります。この障害に対する一般的な原因は次のとおりです。

  • ドメインが存在しないワーカーを設定している。この問題を修正するには、まず Amazon SWF コンソール または Amazon SWF サービスAPI を使用してドメインを登録します。

  • ワークフロー実行または未登録タイプのアクティビティタスクを作成しようとしている。この問題は、ワーカーが実行される前にワークフロー実行を作成しようとすると発生する場合があります。ワーカーは初回実行時にタイプを登録するため、実行を開始する前に 1 回以上実行する (または、コンソールかサービス API を使用して手動でタイプを登録する) 必要があります。タイプが登録されると、実行中のワーカーがなくても実行を作成できます。

  • ワーカーが、すでにタイムアウトしているタスクを実行しようとしている。例えば、ワーカーがタスクの処理に時間がかかりすぎてタイムアウトを超えると、タスクを完了または失敗しようとしたときに UnknownResource 障害が発生します。 AWS Flow Framework ワーカーは引き続き Amazon SWF をポーリングし、追加のタスクを処理します。ただし、タイムアウトの調整を検討する必要があります。タイムアウトを調整するには、新しいバージョンのアクティビティタイプを登録する必要があります。

Promise で get() を呼び出す場合の例外

Java 機能とは異なり、Promise は、ノンブロッキング構築であり、準備状態になっていない Promiseget() を呼び出すと、ブロックされずに例外がスローされます。Promise​ を使用する正しい方法は、これを非同期タスク (またはタスク) に渡して非同期メソッドで値にアクセスすることです。 AWS Flow Framework for Java により、すべての Promise 引数が渡され準備が整った場合にのみ、非同期メソッドが呼び出されます。​ コードが正しいと思われる場合、または AWS Flow Framework サンプルの 1 つを実行中にこのコードを実行した場合は、AspectJ が正しく設定されていないことが原因と考えられます。詳細については、「AWS Flow Framework for Java のセットアップ」セクションを参照してください。

非決定的なワークフロー

非決定論」セクションに記載されているように、ワークフローの実装は決定的である必要があります。非決定論につながる一般的な間違いには、システムクロックの使用、乱数の使用、および GUID の生成などがあります。これらの構成では、返る値や時間が異なる場合があるため、ワークフローの制御フローが実行される度に異なるパスが使用されることがあります (詳細については、「AWS Flow Framework 基本概念: 分散実行」および「表面下の動作」を参照)。ワークフローの実行中にフレームワークで非決定性が検出されると、例外がスローされます。

バージョニングによる問題

新しいバージョンのワークフローやアクティビティを実装する場合 (例: 新しい機能を追加する場合)、適切な注釈 (@Workflow@Activites、または @Activity) を使用してタイプのバージョンを増やす必要があります。新しいバージョンのワークフローがデプロイされると、すでに実行されている既存のバージョンが実行されることがあります。そのため、適切なバージョンのワークフローとアクティビティを持つワーカーがタスクを取得できることを確認します。これを行うには、バージョンごとに異なるタスクリストを使用します。たとえば、タスクリストの名前にバージョン番号を追加することができます。これにより、異なるバージョンのワークフローおよびアクティビティに属するタスクが適切なワーカーに割り当てられます。

ワークフロー実行のトラブルシューティングとデバッグ

ワークフロー実行のトラブルシューティングでは、まず Amazon SWF コンソールを使用してワークフロー履歴を確認します。ワークフロー履歴は、ワークフロー実行の実行状態を変更したすべてのイベントの完全かつ信頼できるレコードです。この履歴は、Amazon SWF で管理されます。また、問題の診断に非常に役立ちます。Amazon SWF コンソールを使用すると、ワークフロー実行を検索し、各履歴イベントを詳細に確認できます。

AWS Flow Framework には、ワークフロー実行をローカルで再生してデバッグするために使用できるWorkflowReplayerクラスが用意されています。このクラスを使用して、クローズ済みおよび実行中のワークフロー実行をデバッグできます。WorkflowReplayer​ は Amazon SWF​ に保存されている履歴に依存して再生を実行します。Amazon SWF アカウントのワークフロー実行をポイントするか、履歴イベントを使用できます (例えば、Amazon SWF から履歴を取得し、後で使用できるようにローカルでシリアル化することができます)。WorkflowReplayer を使用してワークフロー実行を再生しても、アカウントで実行されているワークフロー実行には影響ありません。再生はクライアント上で完全に行われます。デバッグツールを使用して、ワークフローのデバッグ、ブレークポイントの作成、コーディングを行うことができます。Eclipse を使用している場合は、ステップフィルターを追加して AWS Flow Framework パッケージをフィルタリングすることを検討してください。

たとえば、次のコードスニペットは、ワークフロー実行の再生に使用できます。

String workflowId = "testWorkflow"; String runId = "<run id>"; Class<HelloWorldImpl> workflowImplementationType = HelloWorldImpl.class; WorkflowExecution workflowExecution = new WorkflowExecution(); workflowExecution.setWorkflowId(workflowId); workflowExecution.setRunId(runId); WorkflowReplayer<HelloWorldImpl> replayer = new WorkflowReplayer<HelloWorldImpl>( swfService, domain, workflowExecution, workflowImplementationType); System.out.println("Beginning workflow replay for " + workflowExecution); Object workflow = replayer.loadWorkflow(); System.out.println("Workflow implementation object:"); System.out.println(workflow); System.out.println("Done workflow replay for " + workflowExecution);

AWS Flow Framework では、ワークフロー実行の非同期スレッドダンプを取得することもできます。このスレッドダンプでは、オープンのすべての非同期タスクの呼び出しスタックが割り当てられます。この情報は、実行中に保留されており、スタック状態になっているタスクを判断する上で便利です。例:

String workflowId = "testWorkflow"; String runId = "<run id>"; Class<HelloWorldImpl> workflowImplementationType = HelloWorldImpl.class; WorkflowExecution workflowExecution = new WorkflowExecution(); workflowExecution.setWorkflowId(workflowId); workflowExecution.setRunId(runId); WorkflowReplayer<HelloWorldImpl> replayer = new WorkflowReplayer<HelloWorldImpl>( swfService, domain, workflowExecution, workflowImplementationType); try { String flowThreadDump = replayer.getAsynchronousThreadDumpAsString(); System.out.println("Workflow asynchronous thread dump:"); System.out.println(flowThreadDump); } catch (WorkflowException e) { System.out.println("No asynchronous thread dump available as workflow has failed: " + e); }

タスクの消失

タスクが古いワーカーに引き渡されることを確認する場合に限り、ワーカーをシャットダウンし、続けて新しいワーカーをすぐに開始することがあります。この操作は、システム内の競合状態が原因で行う場合があり、複数のプロセスに分散されます。また、この問題は、短い周期でユニットテストを実行している場合にも発生することがあります。Eclipse のテストを停止して、シャットダウンハンドラが呼び出されない場合にも、この現象が起こることもあります。

古いワーカーでタスクが取得されていることによる問題であることを確認するには、ワークフロー履歴を確認し、新しいワーカーが受け取る予定のタスクを受け取ったプロセスを判断する必要があります。たとえば、履歴の DecisionTaskStarted には、タスクを受け取ったワークフローワーカーの識別子が含まれます。フローフレームワークによって使用されているこの ID の形式は、次のとおりです: {processId}@{host name} 例えば、サンプル実行における Amazon SWF コンソールの DecisionTaskStarted イベントの詳細は次のとおりです。

イベントのタイムスタンプ

Mon Feb 20 11:52:40 GMT-800 2012

アイデンティティ

2276@ip-0A6C1DF5

スケジュールされたイベント ID

33

この状況を回避するには、テストごとに異なるタスクリストを使用します。また、古いワーカーのシャットダウンと、新しいワーカーの起動の間に、遅延を追加することを検討してください。