Kafka:按需使用所有消息

时间:2018-12-13 17:15:16

标签: java apache-kafka kafka-consumer-api

目标:阅读主题中的所有消息,然后终止该过程。

我可以通过以下方式连续阅读消息:

props.put("bootstrap.servers", kafkaBootstrapSrv);
props.put("group.id", group_id);
props.put("max.poll.records", 1); // Only get one record at a time. I understand that to read all messages this will need to be increased
props.put("enable.auto.commit", "false");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("MY_TOPIC"));

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(500);

    for (ConsumerRecord<String, String> record : records) {
        process_record(record);
    }

    consumer.commitSync();
}

但是在这种情况下,该过程永远不会终止。当我摆脱

while (true)

循环并运行该程序,它不会从该主题中获取一条记录(我希望有一条记录)。为什么会这样?

1 个答案:

答案 0 :(得分:2)

Kafka主题基本上实现了无数事件。

那么从主题中消费时何时停止?你怎么知道你到达终点了? 简短的答案是你不知道!从理论上讲,制作人可以始终向该主题发送新消息。

实际上,假设没有附加新记录或只有很少新记录,您可以做一些事情来结束。

使用endOffsets()可以找到分区的当前最后偏移量。使用者达到分配给它的所有分区的偏移量后,您可以停止轮询(或刷新它,并查看是否已发送新消息)。

您可以使用position()方法来检索每个分区中的当前位置。在消耗时,每个记录还通过offset()公开其自己的偏移量。因此,您可以使用它们来跟踪向终点偏移的进度。

关于您的第二个问题,poll()首次调用时不返回任何内容。可以预期,因为基本上poll()使客户端正常工作,并且在第一次调用时,它将启动与集群的连接并启动组协议(这需要几秒钟),因此不太可能在之前就已经收到消息poll()返回。