6

AWS Ruby SDK を使用して単純なワークフローとして管理し始めたばかりです。私がすぐに気付いた動作の 1 つは、新しいワークフロー実行を送信する前に、少なくとも 1 つの関連ワーカーと 1 つの関連ディサイダーが実行されている必要があることです。

ワーカーとディサイダーを開始する前に新しいワークフロー実行を送信すると、タイムアウト制限内にある場合でも、タスクが取得されません。どうしてこれなの?HTTP ロング ポーリングがどのように機能するかの説明に基づいて、poll() の呼び出しに到達すると、いずれかのアプリが関連するタスクを受け取ることが期待されます。

ジョブが失敗した後、他のデッドロック状況に遭遇しました (例: ワーカーまたはディサイダーのバグによる、または終了による)。場合によっては、まったく新しいワークフローの実行を再実行したり、開始したりすると、ワークフローの実行がデッドロックすることがあります。最初の決定タスクは、AWS コンソールのワークフロー実行履歴に表示されますが、ディサイダーはそれらを受け取りません。確かに、この問題を確認/テスト ケースに還元するのに苦労していますが、上記の問題に関連していると思われます。これは、およそ 10 ~ 20% の確率で発生します。残りの時間は、すべてが機能します。

他に言及すべき点: 順番に実行される 2 つの別々のアクティビティ タスクに対して、1 つのタスク リストを使用しています。ワーカーとディサイダーの両方が同じタスク リストをポーリングしています。

これが私の労働者です:


require 'yaml'
require 'aws'
 
config_file_path = File.join(File.dirname(File.expand_path(__FILE__)), 'config.yaml')
config = YAML::load_file(config_file_path)
 
swf = AWS::SimpleWorkflow.new(config)
 
domain = swf.domains['test-domain']
 
puts("waiting for an activity")
domain.activity_tasks.poll('hello-tasklist') do |activity_task|
 
  puts activity_task.activity_type.name
  activity_task.complete! :result => name
 
  puts("waiting for an activity")
end

編集

AWS フォーラムの別のユーザーは次のようにコメントしています。

原因は、長いポーリング接続のシャットダウンをすぐに認識しない SWF にあると思います。ワーカーを強制終了すると、しばらくの間その接続はサービスによって開かれていると見なされます。そのため、タスクをディスパッチできます。あなたには、新しい労働者がそれを取得していないように見えます。それを確認する方法は、ワークフローの履歴を確認することです。死んだワーカーのホストと pid を含む識別フィールドを持つアクティビティ タスク開始イベントが表示されます。最終的に、そのようなタスクはタイムアウトになり、ディサイダーによって再試行される可能性があります。

このような状態は、接続を頻繁に終了する単体テスト中に一般的であり、実稼働アプリケーションにとって実際には問題ではないことに注意してください。一般的な回避策は、単体テストごとに異なるタスク リストを使用することです。

これはかなり合理的な説明のようです。これを確認してみます。

4

1 に答える 1

9

あなたは 2 つの問題を提起しました。1 つはアクティブなディサイダーのない実行の開始に関するもので、もう 1 つはタスクの途中でアクターがクラッシュすることに関するものです。それらを順番に説明しましょう。

私はあなたの観察に基づいて実験を行いました。実際、新しいワークフローの実行が開始され、ディサイダーが SWF をポーリングしていない場合でも、新しい決定タスクが開始されたと考えられます。以下は、AWS コンソールからの私のイベント ログです。何が起こるか注意してください:

Fri Feb 22 22:15:38 GMT+000 2013 1 WorkflowExecutionStarted
Fri Feb 22 22:15:38 GMT+000 2013 2 DecisionTaskScheduled
Fri Feb 22 22:15:38 GMT+000 2013 3 DecisionTaskStarted
Fri Feb 22 22:20:39 GMT+000 2013 4 DecisionTaskTimedOut
Fri Feb 22 22:20:39 GMT+000 2013 5 DecisionTaskScheduled
Fri Feb 22 22:22:26 GMT+000 2013 6 DecisionTaskStarted
Fri Feb 22 22:22:27 GMT+000 2013 7 DecisionTaskCompleted
Fri Feb 22 22:22:27 GMT+000 2013 8 ActivityTaskScheduled
Fri Feb 22 22:22:29 GMT+000 2013 9 ActivityTaskStarted
Fri Feb 22 22:22:30 GMT+000 2013 10 ActivityTaskCompleted
...

最初の意思決定タスクはすぐにスケジュールされ (これは予想どおり)、すぐに開始されました (つまり、ディサイダーが実行されていなくても、ディサイダーにディスパッチされたとされています)。その間にディサイダーを開始しましたが、5 分後の元の決定タスクのタイムアウトまでワークフローは動きませんでした。これが望ましい動作になるシナリオは考えられません。それに対する 2 つの防御策として考えられるのは、新しい実行を開始する前にディサイダーを実行するか、決定タスクに許容可能な短いタイムアウトを設定することです (これらのタスクはいずれにせよ即時に実行する必要があります)。

アクター (ディサイダーまたはワーカー) のクラッシュの問題は、私がよく知っている問題です。最初の短い背景メモ:

アクティビティ タスクと決定タスクの両方が、サービスによって次の 3 段階で記録されます。

  • スケジュール済み = アクターがピックアップする準備ができています。
  • 開始済み = アクターによってすでにピックアップされています。
  • 完了/失敗またはタイムアウト = アクターが期限内にタスクを完了または失敗または完了しなかった。

アクターがタスクを取得してクラッシュすると、サービスに何も報告しないことは明らかです (回復できて、まだタスク トークンを記憶している場合を除きます)。しかし、ほとんどのクラッシュ アクターはそれほど賢くはありません)。次に決定タスクがスケジュールされるのは、最近ディスパッチされたタスクのタイムアウト時です。これが、タスクのタイムアウトの間、すべてのアクターがブロックされているように見える理由です。これは実際には望ましい動作です。サービスは、ワーカーが期限内に作業を続けている限り、タスクが処理されているかどうかを認識できません。これに対処する簡単な方法があります。アクターを try-catch ブロックに適合させ、予期しないクラッシュが発生したときにタスクを失敗させます。統合テストごとに個別のタスクリストを使用することはお勧めしません。teardown()代わりに、ブロック内のタスクを失敗させることをお勧めします。SWF ではreason、タスクの失敗に を指定できます。これは、失敗をログに記録し、後で AWS コンソールを介して表示する方法の 1 つです。

于 2013-02-23T00:17:04.830 に答える