为什么我的所有Kafka消息都在Storm中重放?

时间:2015-10-11 01:54:55

标签: java apache-kafka apache-storm

我试图找出为什么每次重新启动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的预期

我的期望: Expected behavior

然而,我使用默认设置的实际行为如下。消息处理得很好,直到我停止管道,然后当我重新启动时,我得到所有消息的重播,包括那些(A和B),我相信我已经知道了

实际发生的事情: EarliestTime, default behavior

根据Matthias提到的configuration options,我可以将startOffsetTime更改为Latest,但这实际上是管道正在丢弃消息的最新消息(消息" C")在管道重启时生成。

LatestTime, messages dropped

我有一个使用NodeJS编写的消费(使用npm kafka-node)能够向Kafka发送消息,当我重新启动NodeJs消费者时,它完全符合我的预期(赶上消息" C"这是在消费者关闭并从那里继续产生的时候产生的 - 所以我如何在KafkaSpout中获得相同的行为?

1 个答案:

答案 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

的实例上启动它