Consumer.endOffsets在Kafka中如何工作?

时间:2018-10-17 22:46:00

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

假设我有一个无限期运行的计时器任务,该任务遍历kafka集群中的所有使用者组,并为每个组的所有分区输出滞后,已提交的偏移量和结束偏移量。与Kafka控制台使用者群组脚本的工作方式类似,不同之处在于它适用于所有群组。

类似

单个使用者-不起作用-不为某些提供的主题分区返回偏移量(例如,提供了10个-返回了5个偏移量)

Consumer consumer;

static {
  consumer = createConsumer();
}

run() { 
  List<String> groupIds = getConsumerGroups();
  for(String groupId: groupIds) {
       List<TopicParition> topicParitions =  getTopicParitions(groupId);
       consumer.endOffsets(topicParitions); -- Not working - missing offsets for some partitions for some groups (in 10 - out 5)
   }
}

多个消费者-工作

run() { 
   List<String> groupIds = getConsumerGroups();
   for(String groupId: groupIds) {
        List<TopicParition> topicParitions =  getTopicParitions(groupId);
        Consumer consumer = createConsumer();
        consumer.endOffsets(topicParitions); This works!!!
   }
 }

版本:Kafka-Client 2.0.0

我是否正确使用了消费者api?理想情况下,我想使用单个消费者。

让我知道是否需要更多详细信息。

2 个答案:

答案 0 :(得分:1)

我认为您快到了。首先收集所有您感兴趣的主题分区,然后发布一个consumer.endOffsets命令。

请记住,我还没有尝试运行它,但是这样的方法应该可以工作:

run() { 
   Consumer consumer = createConsumer();
   List<String> groupIds = getConsumerGroups();
   List<TopicPartition> topicPartitions = new ArrayList<>();

   for (String groupId: groupIds) {
        topicPartitions.addAll(getTopicPartitions(groupId));
   }

   consumer.endOffsets(topicPartitions); 
}

答案 1 :(得分:1)

这是Fetcher.fetchOffsetsByTimes()中的一个错误,特别是在groupListOffsetRequests方法内部,其中的逻辑是不添加分区以进行重试,而领导者请求分区偏移量则未知或不可用。

当您在所有使用者组分区上使用单个使用者时,这一点尤其明显,在某些情况下,当我们请求endoffsets时某些组已经具有主题分区领导者信息,而对于没有领导者信息未知或未知的主题分区,由于该错误,无法使用的功能将被取消。

后来,我意识到从每个消费者组中提取主题分区不是一个好主意,而是进行了更改,以从AdminClient.listTopics & AdminClient.describeTopics中读取主题分区,然后一次全部传递给Consumer.endOffsets

尽管这不能完全解决问题,因为在多次运行之间主题/分区可能仍然不可用或未知。

可以找到更多信息-KAFKA-7044pull request。此问题已修复,计划在2.1.0版本中发布。