这看起来令人困惑,我看到的一些例子中,每个螺栓都会调用元组上的ack,而某些地方并非如此。关于这个的做法是什么?它的含义是什么?
答案 0 :(得分:0)
在互联网和answer上搜索后,我从文档中找到了这个link,这对此非常有帮助。
当一个地点收到来自消息来源的消息说Kafka或Kestrel队列时,它opens
消息。这意味着消息实际上并没有从队列中取出,而是置于"待定"等待确认消息已完成的状态。处于挂起状态时,不会将消息发送给队列的其他使用者。此外,如果客户端断开该客户端的所有挂起消息,则将其重新放回队列。
打开邮件时,Kestrel
会向客户端提供邮件的数据以及邮件的唯一ID。在将元组发送到KestrelSpout
时,message id
将该确切ID用作元组的SpoutOutputCollector
。稍后,当在KestrelSpout上调用ack
或fail
时,KestrelSpout
会向ack
发送fail
或Kestrel
条消息message id
将消息从队列中取出或重新放回。
客户端需要告诉Storm每当它在元组树中创建一个新的链接时也称为锚定,这是通过发出一个新的元组来完成的。
当您完成处理单个元组时,客户端还需要告诉Storm,这由ack
完成。通过执行这两项操作,Storm可以检测元组树何时完全处理,并且可以适当地使spout元组失效或失败。
在下面的示例中,bolt将包含句子的元组拆分为每个单词的元组。通过将输入元组指定为要发出的第一个参数来锚定每个单词元组。由于单词元组被锚定,如果单词元组未能在下游处理,则稍后将重放树根处的spout元组。
public class SplitSentence extends BaseRichBolt {
OutputCollector _collector;
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
}
public void execute(Tuple tuple) {
String sentence = tuple.getString(0);
for(String word: sentence.split(" ")) {
_collector.emit(tuple, new Values(word));
}
_collector.ack(tuple);
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
相反,如果像这样发出单词元组:
_collector.emit(new Values(word));
以这种方式发出单词元组会导致它无法锚定。如果在下游处理元组失败,则不会重放根元组。根据拓扑中所需的容错保证,有时发布未锚定的元组是合适的。
在许多情况下,螺栓遵循读取输入元组的共同模式,基于它发出元组,然后在执行方法结束时执行元组。这些螺栓属于过滤器类别和简单功能。 Storm有一个名为BasicBolt
的接口,它为您封装了这种模式。
以下是SplitSentence
的示例,可以写成BasicBolt
,如下所示:
public class SplitSentence extends BaseBasicBolt {
public void execute(Tuple tuple, BasicOutputCollector collector) {
String sentence = tuple.getString(0);
for(String word: sentence.split(" ")) {
collector.emit(new Values(word));
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
此实现比之前的实现更简单,并且在语义上是相同的。发送到BasicOutputCollector的元组会自动锚定到输入元组,并在execute方法完成时自动为您启用输入元组。
如评论所示,here可以看出,IBasicBolt
会照顾你,所以无论哪个班级都在实施IBasicBolt
:
/**
* Process the input tuple and optionally emit new tuples based on the input tuple.
*
* All acking is managed for you. Throw a FailedException if you want to fail the tuple.
*/
BaseBasicBolt和BaseRichBolt都实现了IBasicBolt
。