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