Kafka使用者仅在第二次通话中使用消息

时间:2018-12-13 06:52:25

标签: java apache-kafka

我正在这样设置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返回所有可用记录
  • 后续调用也会返回所有记录

为什么每次重新启动应用程序时都需要进行两次此操作?我希望话题中的所有事件都已经开始...

0 个答案:

没有答案