上一個問題的回答:https://blog.csdn.net/weixin_37392582/article/details/104685191
1. 場景
當用戶需要獲取數據時,後端從指定 topic 下消費1條數據;每次操作的間隔爲 0~;
每個 topic 只有一個 消費者。
2. 現象
多個topic同時消費數據,經常出現“獲取數據失敗”的問題;所有的消費者均在一個 group 內。
3. 問題排查路徑
- 查看日誌,發現了一個之前一直忽視的問題, 每當出現“數據獲取失敗”的問題, kafka都處於 Reblance 的狀態,而 Reblacne 會導致同一 Group 內的所有 Consumer 都不能工作;
- 在這裏發現了兩個問題, 一是頻繁 Reblance, 二是消費者全都處於同一羣組;
- 第二個問題很好解決,因爲“每個topic只有一個consumer消費數據”,因此對每個topic,都有一個獨立的 group 來消費它;
- 對於第一個問題,“consumer.session.timeout.ms”參數值爲 30000 ,即30s 。因爲消費數據的間隔很長,所以基本上每拿一條數據, 都會觸發 Reblance 操作,將參數值修改爲 299500, “consumer.request.timeout.ms” 修改爲 300000, 還有 500ms 爲 “fetch.max.wait.ms” 的默認值。
- 至此,問題解決。
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());
}
}
}