我正在这样设置kafka用户:
private Consumer<String, HistoryEvent> createConsumer(Configuration configuration) {
Properties baseProperties = getKafkaBaseProperties(configuration);
baseProperties.remove("key.serializer");
baseProperties.remove("value.serializer");
baseProperties.setProperty("group.id", String.format("%s-group", applicationTopicName));
return new KafkaConsumer<>(baseProperties);
}
private void setupConsumer() {
topicConsumer.subscribe(Collections.singleton(applicationTopicName), consumerListener);
}
然后我试图像这样从消费者那里查询主题的整个变更日志:
topicConsumer.seekToBeginning(consumerListener.getActivePartitions());
List<HistoryEvent> events = new ArrayList<>();
ConsumerRecords<String, HistoryEvent> records = topicConsumer.poll(Duration.ofSeconds(1));
while (!records.isEmpty() || hasPendingMessages.apply(topicConsumer.endOffsets(consumerListener.getActivePartitions()).entrySet())) {
events.addAll(StreamSupport.stream(records.spliterator(), false)
.filter(record -> flowId.equals(record.key()))
.map(ConsumerRecord::value)
.collect(Collectors.toList())
);
records = topicConsumer.poll(Duration.ofSeconds(1));
}
通常,此代码可以工作并返回该主题中的所有文档,但是只有在第二次调用后才这样做。从代码中可以看到,有一个主题分区侦听器,当分配方或从使用者撤销分区时,该主题将被通知。我为此添加了调试器,可以观察到以下情况:
topicConsumer.subscribe
->分区侦听器无任何作用cusomerListener.getActivePartitions()
为空,因为从未使用分配调用主题分配的侦听器。根据{{1}}的源代码,这意味着它将搜索所有分配。seekToBeginning
被调用。在通话期间,topicConsumer.poll()
调用了我的监听器,其中包含一个空的分区集合(??)onPartitionsRevoked
(根据结束偏移量检查分区偏移量)也会返回false->根本不存储任何事件hasPendingMessages
仍然为空,因为到目前为止,仅使用空的consumerListener.getActivePartitions()
onPartitionsRevoked
被调用。在通话期间,topiConsumer.poll()
中使用该主题存在的单个分区调用了我的侦听器onPartitionsAssigned
返回所有可用记录为什么每次重新启动应用程序时都需要进行两次此操作?我希望话题中的所有事件都已经开始...