我试图找出为什么每次重新启动Storm拓扑时我的所有Kafka消息都会被重播。
我理解它应该如何工作是因为一旦最后一个Bolt得到了元组,那么spout应该在Kafka上提交消息,因此我不应该在重启后看到它重放。
我的代码是一个简单的Kafka-spout和Bolt,它只打印每条消息,然后确认它们。
private static KafkaSpout buildKafkaSpout(String topicName) {
ZkHosts zkHosts = new ZkHosts("localhost:2181");
SpoutConfig spoutConfig = new SpoutConfig(zkHosts,
topicName,
"/" + topicName,
"mykafkaspout"); /*was:UUID.randomUUID().toString()*/
spoutConfig.scheme = new SchemeAsMultiScheme(new StringScheme());
return new KafkaSpout(spoutConfig);
}
public static class PrintBolt extends BaseRichBolt {
OutputCollector _collector;
public static Logger LOG = LoggerFactory.getLogger(PrintBolt.class);
@Override
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
}
@Override
public void execute(Tuple tuple) {
LOG.error("PrintBolt.0: {}",tuple.getString(0));
_collector.ack(tuple);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("nothing"));
}
}
public static void main(String[] args) throws Exception {
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("kafka", buildKafkaSpout("mytopic"), 1);
builder.setBolt("print1", new PrintBolt(),1).shuffleGrouping("kafka");
}
我没有提供任何配置设置,而不是代码中的设置。
我错过了配置设置或我做错了什么?
更新
澄清一下,在重新启动管道之前一切正常。以下行为是我可以在其他(非风暴)消费者中得到的,以及我对KafkaSpout的预期
然而,我使用默认设置的实际行为如下。消息处理得很好,直到我停止管道,然后当我重新启动时,我得到所有消息的重播,包括那些(A和B),我相信我已经知道了
根据Matthias提到的configuration options,我可以将startOffsetTime
更改为Latest
,但这实际上是管道正在丢弃消息的最新消息(消息" C")在管道重启时生成。
我有一个使用NodeJS编写的消费(使用npm kafka-node)能够向Kafka发送消息,当我重新启动NodeJs消费者时,它完全符合我的预期(赶上消息" C"这是在消费者关闭并从那里继续产生的时候产生的 - 所以我如何在KafkaSpout中获得相同的行为?
答案 0 :(得分:3)
问题出在提交代码中 - 如果在没有拓扑名称的情况下运行LocalCluster
,并且本地群集不捕获,则提交拓扑的模板代码将创建storm jar
的实例国家,因此重播。
所以
$ storm jar myjar.jar storm.myorg.MyTopology topologyname
将在我的single node development cluster上启动它,
$ storm jar myjar.jar storm.myorg.MyTopology
将在LocalCluster