One
: IBolt
: defines the function set of Bolt, mainly including
void prepare(Map stormConf,TopologyContext context,
OutputCollector collector);
void execut(e Tuple input);
void cleanup();
three methods
Two:
IRichBolt
:
Need to implement IBolt and IComponent interfaces
public interface IRichBolt extends IBolt, IComponent {
}
Three:
IBasicBolt:
The interface definition is basically the same as IBolt, and the specific implementation requirements are also the same as IBolt.
The difference lies in the following two points:
1: His collector uses BasicOutputCollector , and this parameter is placed in the execute method, not in perpare
2: He implements the IComponent interface
source code:
public interface
IBasicBolt
extends
IComponent {
void
prepare(Map stormConf, TopologyContext context);
/**
* 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.
*/
void
execute(Tuple input, BasicOutputCollector collector);
void
cleanup();
}
为什么会有这个接口,作用是提供一种更简单的Bolt编写方式,基于
IBasicBolt编写的好处是storm框架帮你处理发出消息的Ack,Fail和Anchor操作,这是由执行器
BasicBoltExecutor
实现的。
BasicBoltExecutor 已经帮你实现了IRichBolt
源码:
public class
BasicBoltExecutor
implements
IRichBolt {
public static final
Logger
LOG
= LoggerFactory.
getLogger
(BasicBoltExecutor.
class
);
private
IBasicBolt
_bolt
;
private transient
BasicOutputCollector
_collector
;
public
BasicBoltExecutor(IBasicBolt bolt) {
_bolt
= bolt;
}
public void
declareOutputFields(OutputFieldsDeclarer declarer) {
_bolt
.declareOutputFields(declarer);
}
public void
prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
_bolt
.prepare(stormConf, context);
_collector
=
new
BasicOutputCollector(collector);
}
public void
execute(Tuple input) {
_collector
.setContext(input);
try
{
_bolt
.execute(input,
_collector
);
_collector
.getOutputter().ack(input);
}
catch
(FailedException e) {
if
(e
instanceof
ReportedFailedException) {
_collector
.reportError(e);
}
_collector
.getOutputter().fail(input);
}
}
public void
cleanup() {
_bolt
.cleanup();
}
public
Map<String, Object> getComponentConfiguration() {
return
_bolt
.getComponentConfiguration();
}
}
四 :IBatchBolt
IBatchBolt主要用于storm中的批处理,目前storm主要用该接口来实现消息的可靠传输,storm的事务Topology以及Trident主要是基于IBatchBolt的,相比以上三个,它多了一个
finishBatch 方法,它在一个批处理结束时候被调用。此外,
IBatchBolt还除去了cleanup方法。
public class
BatchBoltExecutor
implements
IRichBolt, FinishedCallback, TimeoutCallback {
public static final
Logger
LOG
= LoggerFactory.
getLogger
(BatchBoltExecutor.
class
);
byte
[]
_boltSer
;
Map<Object, IBatchBolt>
_openTransactions
;
Map
_conf
;
TopologyContext
_context
;
BatchOutputCollectorImpl
_collector
;
public
BatchBoltExecutor(IBatchBolt bolt) {
_boltSer
= Utils.
javaSerialize
(bolt);
}
@Override
public void
prepare(Map conf, TopologyContext context, OutputCollector collector) {
_conf
= conf;
_context
= context;
_collector
=
new
BatchOutputCollectorImpl(collector);
_openTransactions
=
new
HashMap<>();
}
@Override
public void
execute(Tuple input) {
Object id = input.getValue(
0
);
IBatchBolt bolt = getBatchBolt(id);
try
{
bolt.execute(input);
_collector
.ack(input);
}
catch
(FailedException e) {
LOG
.error(
"Failed to process tuple in batch"
, e);
_collector
.fail(input);
}
}
@Override
public void
cleanup() {
}
@Override
public void
finishedId(Object id) {
IBatchBolt bolt = getBatchBolt(id);
_openTransactions
.remove(id);
bolt.finishBatch();
}
@Override
public void
timeoutId(Object attempt) {
_openTransactions
.remove(attempt);
}
@Override
public void
declareOutputFields(OutputFieldsDeclarer declarer) {
newTransactionalBolt().declareOutputFields(declarer);
}
@Override
public
Map<String, Object> getComponentConfiguration() {
return
newTransactionalBolt().getComponentConfiguration();
}
private
IBatchBolt getBatchBolt(Object id) {
IBatchBolt bolt =
_openTransactions
.get(id);
if
(bolt==
null
) {
bolt = newTransactionalBolt();
bolt.prepare(
_conf
,
_context
,
_collector
, id);
_openTransactions
.put(id, bolt);
}
return
bolt;
}
private
IBatchBolt newTransactionalBolt() {
return
Utils.
javaDeserialize
(
_boltSer
, IBatchBolt.
class
);
}
}