繁体   English   中英

消息处理失败后,Kafka消费者恢复

[英]Kafka consumer recover after failed message processing

我正在我的一个项目中使用简单的kafka Consumer,我希望的逻辑是当消费者无法处理某些消息时它将提交最后正确处理的消息,然后在下次轮询时它将从失败的消息继续。

我尝试使用以下代码手动提交每条消息:

public void fetchMessages() {
  ConsumerRecords<String, MyObject> messages = kafkaConsumer.poll(10000);
  for (ConsumerRecord message : messages) {
      logger.info("Reading kafka message, topic ["+kafkaTopic+"], partition ["+message.partition()+"], offset ["+message.offset()+"]");
      try {
          MyObject myObject = (MyObject) message.value();
          logger.info("Handling message," + myObject);
          handleMessage(myObject);
          commitMessage(message);
      } catch (Exception e) {
          logger.error("Error handling message");              throw e;
      }
  }
}


private void commitMessage(ConsumerRecord message) {
        long              nextOffset        = message.offset() + 1;

        TopicPartition    topicPartition    = new TopicPartition(kafkaTopic,message.partition());
        OffsetAndMetadata offsetAndMetadata = new OffsetAndMetadata(nextOffset);

        Map<TopicPartition,OffsetAndMetadata> offsetAndMetadataMap = new HashMap<>();
        offsetAndMetadataMap.put(topicPartition,offsetAndMetadata);

        logger.info("Commiting processed kafka message, topic ["+kafkaTopic+"], partition ["+message.partition()+"], next offset ["+nextOffset+"]");
        kafkaConsumer.commitSync(offsetAndMetadataMap);
}

但是例如当我从不同的分区获取3条消息时,我成功处理第一条消息然后无法处理第二条消息,我只是退出ConsumerRecord进行循环,我希望获得相同的2条消息,我还没有提交但在下一个poll迭代中。 相反,消费者只是继续接收新消息,永远不会回到失败的消息。

还试图在失败的消息上应用seek ,然后退出循环,但它正在1分区上工作,不能在很多上工作。

kafkaConsumer.seek(new TopicPartition(kafkaTopic,message.partition()),message.offset());    

一些细节:

  • 主题有12个分区
  • 所有分区的一个消费者
  • 消费者每分钟执行一次轮询循环
  • enable.auto.commit:false

我的代码或逻辑有什么问题?

我发现了搜索是如何工作的,并且在失败的消息中,我必须为当前消费者的所有分区寻找所有偏移。

private void seekAllPartitions() {
    logger.info("Processing of some kafka message was failed, seeking all partitions to last committed");
    List<PartitionInfo> partitionInfos = kafkaConsumer.partitionsFor(kafkaTopic);
    for (PartitionInfo partitionInfo : partitionInfos) {
        TopicPartition topicPartition = new TopicPartition(kafkaTopic, partitionInfo.partition());
        OffsetAndMetadata committedForPartition = kafkaConsumer.committed(topicPartition);
        if (committedForPartition != null) {
            kafkaConsumer.seek(topicPartition,committedForPartition.offset());
        }
    }
}

当某个分区上某个使用者组的最后一次偏移尚未设置时,需要空检查committedForPartition(未知)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM