簡體   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