是否有必要在暴风雨中使用元组

时间:2017-11-01 05:57:47

标签: apache-storm

这看起来令人困惑,我看到的一些例子中,每个螺栓都会调用元组上的ack,而某些地方并非如此。关于这个的做法是什么?它的含义是什么?

1 个答案:

答案 0 :(得分:0)

在互联网和answer上搜索后,我从文档中找到了这个link,这对此非常有帮助。

spout如何处理消息:

当一个地点收到来自消息来源的消息说Kafka或Kestrel队列时,它opens消息。这意味着消息实际上并没有从队列中取出,而是置于"待定"等待确认消息已完成的状态。处于挂起状态时,不会将消息发送给队列的其他使用者。此外,如果客户端断开该客户端的所有挂起消息,则将其重新放回队列。

打开邮件时,Kestrel会向客户端提供邮件的数据以及邮件的唯一ID。在将元组发送到KestrelSpout时,message id将该确切ID用作元组的SpoutOutputCollector。稍后,当在KestrelSpout上调用ackfail时,KestrelSpout会向ack发送failKestrel条消息message id将消息从队列中取出或重新放回。

Ack何时需要:

客户端需要告诉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));

以这种方式发出单词元组会导致它无法锚定。如果在下游处理元组失败,则不会重放根元组。根据拓扑中所需的容错保证,有时发布未锚定的元组是合适的。

何时不需要Ack:

在许多情况下,螺栓遵循读取输入元组的共同模式,基于它发出元组,然后在执行方法结束时执行元组。这些螺栓属于过滤器类别和简单功能。 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.
 */

BaseBasicBoltBaseRichBolt都实现了IBasicBolt