繁体   English   中英

如何在java中一一从Kafka Consumer获取消息?

[英]How to get messages from Kafka Consumer one by one in java?

我正在使用 Apache Kafka API 并尝试一次只获取一条消息。 我只写一个主题。 我可以通过带有文本框的弹出 UI 屏幕来发送和接收消息。 我在文本框中输入一个字符串,然后单击“发送”。 我可以发送任意数量的消息。 假设我发送了 3 条消息,我的 3 条消息是“嗨”、“大声笑”、“再见”。 还有一个“接收”按钮。 现在,使用TutorialsPoint 中的传统代码,当我单击接收按钮时,我会立即在控制台上打印出所有 3 条消息(嗨,大声笑,再见)。 但是,当我在 UI 上单击“接收”时,我只想一次打印一条消息。 例如,我第一次按下接收按钮时,它会打印“hi”,第二次是“lol”,第三次是“bye”。 我是 Kafka 的新手,对如何做到这一点感到困惑。 我尝试从代码中删除两个循环,所以它只有

ConsumerRecords<String, String> records = consumer.poll(100);
System.out.printf(records.iterator().next().value());

如果我只有这两行代码,当我第一次点击接收按钮时,它会打印“嗨”,但第二次按下它时,会收到消息“尝试心跳失败,因为组正在重新平衡 kafka。” 当我设置 max.poll.records = 1 时也出现错误,因为我最终想要我的所有消息,但是当按下接收按钮时,只需要将其中一个消息记录到控制台。 下一次,未记录主题中的下一条消息将被记录。

希望这是有道理的! 感谢任何帮助! 提前致谢!

编辑:包含队列后的新代码,因此我们可以在发送和接收消息之间交替并在有新消息时更新队列:

        if (payloadQueue.isEmpty()){
            ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(500));
            if (records.isEmpty()) {
                log.info("No More Records to Add");
                consumer.close();
            }
            else {
                records.iterator().forEachRemaining(record -> {
                    log.info("RECORD: " + record);
                    payloadQueue.offer(record);
                });
                payload = payloadQueue.poll().value();
                log.info("Received event from KAFKA on subject {} with payload \"{}\"", subject, payload);
            }
        }
        else {
            payload = payloadQueue.poll().value();
            log.info("Received event from KAFKA on subject {} with payload \"{}\"", subject, payload);
        }

Kafka使用batch get来提升性能,真的没必要设置max.poll.records=1。
通过一些变通方法可以轻松实现您想要的。

解决方案

您可以有一个Queue来存储消息,每次按下接收按钮时,您从队列中轮询一条消息,如果队列为空,则调用consumer.poll来填充队列。

代码

    private Queue<ConsumerRecord<String,String>> queue=new LinkedList<>();
    KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
    public void buttonPressed(){
        if (queue.isEmpty()){
            consumer.poll(100).iterator().forEachRemaining(record->queue.offer(record));
        }else {
            System.out.println(queue.poll());
        }
    }

您应该按照@haoyu 的建议添加一个队列,但手动提交消耗的偏移量。 否则,应用程序重置可能会导致数据丢失(因为消息已从主题中消费,尽管没有打印到 UI 中)。

建议阅读KafkaConsumer javadoc 的“手动偏移控制”和“在 Kafka 之外存储偏移”部分。

暂无
暂无

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

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