如何获取卡夫卡中未提交的消息

时间:2019-06-17 12:45:23

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

我在Java中有一个函数,试图在该函数中读取未读的消息。例如,如果我在代理中有offSet 0,1,2的消息已经被使用者读取,并且如果我关闭了我的使用者一个小时。那时我产生的消息偏移量为3、4、5。之后,当我的使用者启动时,它应该从偏移量3而不是从0开始读取消息。但是,它要么读取所有消息,要么读取启动Kafka使用者后产生的消息。我想阅读未读或未提交的邮件

我尝试了"auto.offset.reset"= "latest""earliest"。以及"enable.auto.commit" = "true""false"。在调用commitSync()方法之前,我也尝试过commitAsync()close(),但是没有运气。

public static KafkaConsumer createConsumer() {

    Properties properties = new Properties();
    properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, Constants.KAFKA_BROKER);
    properties.put(ConsumerConfig.GROUP_ID_CONFIG, "testGroup");
    properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
    properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
    properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); 
    properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, "50");
    properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1");
    properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);

    KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);

    consumer.subscribe(Collections.singleton(Constants.TOPIC));
    return consumer;

}

public static void main(String [] args){

    System.out.println("");
    System.out.println("----------------");
    System.out.println("");
    System.out.println("KAFKA CONSUMER EXAMPLE");
    System.out.println("");
    System.out.println("----------------");
    System.out.println("");

    OffsetAndMetadata offsetAndMetadataInitial = createConsumer().committed(new TopicPartition(Constants.TOPIC, 0));

    System.out.println("");
    System.out.println("Offset And MetaData Initial : ");
    System.out.println(offsetAndMetadataInitial);
    System.out.println("");

    ConsumerRecords<String, String> consumerRecords = createConsumer().poll(Duration.ofSeconds(2L));

    System.out.println("");
    System.out.println("Count Consumer Records : " + consumerRecords.count());
    System.out.println("");

    Iterator<ConsumerRecord<String, String>> itr = consumerRecords.iterator();
    Map<TopicPartition, OffsetAndMetadata> partationOffsetMap = new HashMap<>(4);

    while (itr.hasNext()) {

        ConsumerRecord record = itr.next();

        System.out.println("OffSet : " + record.offset());
        System.out.println("");
        System.out.println("Key : " + record.key());
        System.out.println("Value : " + record.value());
        System.out.println("Partition : " + record.partition());
        System.out.println("--------------------------");
        System.out.println("");

    }



    createConsumer().close();

}

我只想在kafka Consumer中仅获取未读消息。如果我在某个地方不对,请纠正我。在此先感谢

1 个答案:

答案 0 :(得分:3)

代码中的主要问题是您没有关闭用于轮询消息的使用者。这是因为每次对createConsumer()的调用都会创建一个新的KafkaConsumer。而且由于您没有关闭使用者,并且只调用一次poll(),所以您永远不会提交已阅读的消息。

(具有自动提交功能,在自动提交间隔之后,在poll()中以及在close()中调用commit)

一旦您更正了它可以使用以下设置:

  • auto-commit = true(否则,您也可以手动提交,但自动提交更简单)。
  • offset-reset =最早(这仅在您第一次使用给定的组ID时生效,以告诉您是否要从主题开始进行消费,还是仅在开始消费后才生成消息。)已经开始使用给定的组ID进行消耗,那么您将始终从您已提交的最新偏移量开始消耗。)
  • group-id在两次重启之间不得更改,否则您将根据偏移量重置设置从头开始或从头开始。

希望这会有所帮助