Kafka Consumer 執行 poll 操作時獲取空數據的原因分析(2)


上一個問題的回答:https://blog.csdn.net/weixin_37392582/article/details/104685191


1. 場景

當用戶需要獲取數據時,後端從指定 topic 下消費1條數據;每次操作的間隔爲 0~;
每個 topic 只有一個 消費者。

2. 現象

多個topic同時消費數據,經常出現“獲取數據失敗”的問題;所有的消費者均在一個 group 內。

3. 問題排查路徑

  1. 查看日誌,發現了一個之前一直忽視的問題, 每當出現“數據獲取失敗”的問題, kafka都處於 Reblance 的狀態,而 Reblacne 會導致同一 Group 內的所有 Consumer 都不能工作;
  2. 在這裏發現了兩個問題, 一是頻繁 Reblance, 二是消費者全都處於同一羣組;
  3. 第二個問題很好解決,因爲“每個topic只有一個consumer消費數據”,因此對每個topic,都有一個獨立的 group 來消費它;
  4. 對於第一個問題,“consumer.session.timeout.ms”參數值爲 30000 ,即30s 。因爲消費數據的間隔很長,所以基本上每拿一條數據, 都會觸發 Reblance 操作,將參數值修改爲 299500, “consumer.request.timeout.ms” 修改爲 300000, 還有 500ms 爲 “fetch.max.wait.ms” 的默認值。
  5. 至此,問題解決。

4. 總結經驗

需要面向應用場景思考問題

5. 遺留問題

出現過此類問題, records 獲取到了數據,但是在提交偏移量時,出現了“提交失敗”的錯誤,顯示處於“Reblance”中。
爲什麼 reblance 會發生在 poll 拿到數據後進行?

try {
            records = consumer.poll(Long.parseLong(ConfigClient.instance().get(config, CONSUMER_POLL_TIMEOUT_MS)));
        } catch (Exception e) {
            LOGGER.error(e.toString());
        }
        if (null != records && !records.isEmpty()) {
            for (ConsumerRecord<String, DomainEvent> record : records) {
                LOGGER.info("topic = {}, partition = {}, offset = {}, key = {}, domainEvent = {}\n",
                        record.topic(), record.partition(), record.offset(), record.key(), record.value());
                currentOffsets.put(new TopicPartition(record.topic(), record.partition()), new OffsetAndMetadata(record.offset() + 1, "no metadata"));
                DomainEvent evt = record.value();
                events.add(evt);
                try {
                    consumer.commitSync();
                } catch (CommitFailedException e) {
                    LOGGER.error("檢查對Kafka失去連接的異常處理!");
                    LOGGER.error(e.toString());
                } catch (Exception e) {
                    LOGGER.error(e.getMessage());
                }
            }
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章