IRichBolt和IBasicBolt对比

作为storm的使用者,有两件事情要做以更好的利用storm的可靠性特征。 首先,在你生成一个新的tuple的时候要通知storm; 其次,完成处理一个tuple之后要通知storm。 这样storm就可以检测整个tuple树有没有完成处理,并且通知源spout处理结果。storm提供了一些简洁的api来做这些事情。

由一个tuple产生一个新的tuple称为: anchoring。你发射一个新tuple的同时也就完成了一次anchoring。看下面这个例子: 这个bolt把一个包含一个句子的tuple分割成每个单词一个tuple。

public class SplitSentence implements IRichBolt {   
            Output Collector _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,newValues(word));   
                }   
                _collector.ack(tuple);   
            }   

            public void cleanup() {   
            }   

            public void declareOutputFields(OutputFieldsDeclarer declarer) {   
                declarer.declare(newFields("word"));   
            }   
        }    

我们通过anchoring来构造这个tuple树,最后一件要做的事情是在你处理完当个tuple的时候告诉storm, 通过OutputCollector类的ack和fail方法来做,如果你回过头来看看SplitSentence的例子, 你可以看到“句子tuple”在所有“单词tuple”被发出之后调用了ack。

你可以调用OutputCollector 的fail方法去立即将从消息源头发出的那个tuple标记为fail, 比如你查询了数据库,发现一个错误,你可以马上fail那个输入tuple, 这样可以让这个tuple被快速的重新处理, 因为你不需要等那个timeout时间来让它自动fail。

每个你处理的tuple, 必须被ack或者fail。因为storm追踪每个tuple要占用内存。所以如果你不ack/fail每一个tuple, 那么最终你会看到OutOfMemory错误。

大多数Bolt遵循这样的规律:读取一个tuple;发射一些新的tuple;在execute的结束的时候ack这个tuple。这些Bolt往往是一些过滤器或者简单函数。Storm为这类规律封装了一个BasicBolt类。如果用BasicBolt来做, 上面那个SplitSentence可以改写成这样:

public class SplitSentence implements IBasicBolt {   
            public void prepare(Map conf,   
                                TopologyContext context) {   
            }   

            public void execute(Tuple tuple,   
                                BasicOutputCollector collector) {   
                String sentence = tuple.getString(0);   
                for(String word: sentence.split(" ")) {   
                    collector.emit(newValues(word));   
                }   
            }   

            public void cleanup() {   
            }   

            public void declareOutputFields(   
                            OutputFieldsDeclarer declarer) {   
                declarer.declare(newFields("word"));   
            }   
        }    

这个实现比之前的实现简单多了, 但是功能上是一样的。

发送到BasicOutputCollector的tuple会自动和输入tuple相关联,而在execute方法结束的时候那个输入tuple会被自动ack的。
我们编写的时候使用IBasicBolt最方便了。或者 extends BaseBasicBolt类

Storm 中 IRichBolt 与 IBasicBolt(接口):

在Storm中,如果要保证消息发送成功,每个处理tuple,都必须进行ack或者fail。

因为storm追踪每个tuple要占用内存。所以如果你不ack/fail每一个tuple,那么最终会看到OutOfMemory错误。
通常情况下,实现一个Bolt,可以实现IRichBolt接口或继承BaseRichBolt;如果不想自己处理结果反馈,
可以实现IBasicBolt接口或继承BaseBasicBolt,它实际上相当于自动做掉了prepare方法和collector.emit.ack(inputTuple)。
直接用BasicBolt,会在execute()后自动ack/fail Tuple,而RichBolt则需要自行调用ack/fail。
那什么时候使用RichBolt? Bolt不是在每次execute()时立刻产生新消息,需要异步的发送新消息(比如聚合一段时间的数据再发送)时,又或者想异步的ack/fail原消息时就需要。
BasicBolt的prepare()里并没有collector参数,只在每次execute()时传入collector。而RichBolt刚好相反,你可以在初始化时就把collector保存起来,用它在任意时候发送消息。
另外,如果用RichBolt的collector,还要考虑在发送消息时是否带上传入的Tuple,如果不带,则下游的处理节点出错也不会回溯到Spout重发。用BasicBolt则已默认带上。

Storm 中 BaseBasicBolt和BaseRichBolt:

在BaseBasicBolt中,BasicOutputCollector在emit数据的时候,会自动和输入的tuple相关联,而在execute方法结束的时候那个输入tuple会被自动ack。 

在使用BaseRichBolt需要在emit数据的时候,显示指定该数据的源tuple要加上第二个参数anchor tuple,以保持tracker链路,
即collector.emit(oldTuple, newTuple);并且需要在execute执行成功后调用OutputCollector.ack(tuple), 当失败处理时,执行OutputCollector.fail(tuple);

storm

conf.setNumWorkers(workers); //设置worker数量
uilder.setBolt(“2”, new WordSpliter(),4) //设置Executor并发数量
builder.setBolt(“2”, new WordSpliter(),4).setNumTasks(1); //设置每个线程处理的Task数量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值