web-dev-qa-db-ja.com

ボルトのチェーンでストームをACKする適切な方法

StormでAck-ingがどのように機能するかを確認したいだけです。 1つの注ぎ口と2つのボルトがチェーンされています。スパウトはタプルをボルト1に放出し、次にボルト2にタプルを放出します。ボルト2に、スパウトから送信された最初のタプルを確認させたいのですが、方法がわかりません。

フォールトトレランスを保証するために(つまり、タプルが再送される)、プロセスのどこかで失敗した場合に備えて、スパウトから放出されたタプルをボルト2で確認し、再送できるようにします。

この例を考えてみましょう。

注ぎ口:

 _collector.emit(new Values(queue.dequeue())

ボルト1:

def execute(Tuple: Tuple) {
 _collector.emit(Tuple, new Values("stuff"))
}

この時点で、タプルは注ぎ口から送信されたタプルです。私はここで問題なくそれを確認することができます。次に、Bolt1によって放出されたタプルをリッスンする別のボルトを追加します。

Bolt2:

def execute(Tuple2: Tuple) {
 _collector.emit(Tuple2, new Values("foo"))
}

この時点で、Tuple2のタプルはBolt1から送信されたタプル(文字列「stuff」が含まれているタプル)です。
したがって、Bolt2でackを送信すると、Spoutから送信されたタプルではなくBolt1からタプルがackされます。正しい?

注ぎ口から送信されたタプルをどのように確認できますか?最後のボルトでそれを回収して確認できるように、他のすべての注ぎ口に最初の注ぎ口をピギーバックする必要がありますか?

Nathanのチュートリアルを読んだところ、Tuple2を発行した直後に、Bolt1(Spoutから)で受け取ったTupleを確認できるという印象を受けました。これにより、新しく発行されたタプル2がスパウトによって送信された元のタプルにリンクされるため、ボルト2がタプル2をアックすると、実際にはスパウトから元のタプルがアックされます。これは本当ですか?

説明に何か足りないものがあれば教えてください。

24
Adrian

興味のある人のために、私は嵐のグループに尋ねることによって解決策を見つけました。私が必要としているのは、Spoutで次の方法でタプルを発行することです(一意のIDを使用)。

注ぎ口:

 //ties in Tuple to this UID
 _collector.emit(new Values(queue.dequeue(), *uniqueID*) 

次に、Bolt1は、Bolt2にタプルを放出した後にのみタプルを確認します。

ボルト1:

 //emit first then ack
 _collector.emit(Tuple, new Values("stuff")) //**anchoring** - read below to see what it means
 _collector.ack(Tuple) 

この時点で、SpoutからのタプルはBolt1で確認されていますが、同時に、Bolt2に新しく放出されたタプル「スタッフ」はSpoutからのタプルに「アンカー」されています。これが意味することは、それが後でまだ確認される必要があるということです、さもなければタイムアウトでそれは注ぎ口によって再送されます。

Bolt2:

 _collector.ack(Tuple) 

Bolt2は、Bolt1から受け取ったタプルをackする必要があります。これにより、Spoutが待機していた最後のackが送信されます。この時点でBolt2がTupleを発行する場合、それを取得してackするBolt3が必要です。タプルが最後の時点で確認されていない場合、スパウトはタイムアウトして再送信します。

ボルトからボルトへのemitステートメントでアンカーが実行されるたびに、「ツリー」構造の新しいノードが構築されます...同じタプルを2に送信することはないため、私の場合はリストのようになります。タプル以上の場合、私は1対1の関係にあります。

ツリー内のすべてのノードを確認する必要があります。そうすると、タプルは完全に到着したものとしてマークされます。タプルが確認応答されず、UIDとともに送信され、後でアンカーされた場合、タプルは(確認応答されるまで)永久にメモリに保持されます。

お役に立てれば。

28
Adrian

anchorタプルする必要があります。 Guaranteeing-message-processing を見てください。特にこれが必要です。

List<Tuple> anchors = new ArrayList<Tuple>();
anchors.add(Tuple1);
anchors.add(Tuple2);
_collector.emit(anchors, new Values(1, 2, 3));
0
Vor

これについては 公式ドキュメント で読むことができます。

すべてのボルト全体でトゥープルの実行を追跡する場合は、この動作がすでに定義されている親クラスとしてBaseBasicBoltを使用できます。

その他のユースケース(つまり、最後のボルトで実行する前にタプルを確認する必要がある場合)では、タプル間のリンクを手動で定義する必要があります(アンカーと呼ばれます)。ドキュメントを参照してください。

0
thisismydesign