我观察到,卡夫卡消费者的滞后时间在运行数小时/天后突然开始增加。
检查日志后,我看到很多异常:
org.apache.kafka.clients.consumer.RetriableCommitFailedException:偏移提交失败,并出现可重试的异常。您应尝试重新提交最新消耗的偏移量。
我的ConsumerThread类:
public class ConsumerThread implements Runnable {
private final KafkaConsumer<String, Map<String, Object>> consumer;
public ConsumerThread(
this.consumer = new KafkaConsumer<>(getConsumerConfig(kafkaConfiguration));
}
@Override
public void run() {
try {
consumer.subscribe(topicList);
while (true) {
ConsumerRecords<String, Map<String, Object>> records =
consumer.poll(Duration.ofMillis(kafkaConfiguration.getPollIntervalMs()));
long startPerPoll = System.nanoTime();
for (final ConsumerRecord<String, Map<String, Object>> record : records) {
// message processing logic here
}
consumer.commitAsync((offsets, exception) -> {
if (exception != null) {
//log.error(exception.getMessage());
log.info("exception while committing offset, consumerThread: {}, exception: {}", Thread.currentThread().getName(), exception);
exception.printStackTrace();
}
});
}
} catch (Exception e) {
// ignore for shutdown
log.info("exception in run for consumerThread: {}", e);
} finally {
try {
if (Objects.nonNull(consumer)) {
consumer.commitSync();
}
} finally {
if (Objects.nonNull(consumer)) {
consumer.close();
}
}
}
}
我的kafka配置:
groupId: cep-cg
autoCommitEnabled: false
sessionTimeoutMs: 30000
heartBeatIntervalMs: 10000
autoOffsetReset: latest
maxPollRecord: 250
maxPollIntervalMs: 180000
requestTimeoutMs: 240000
pollIntervalMs: 3000
我检查了关于stackoverflow的其他答案,并进行了一些调整,但似乎都无效。
我想知道的是:
任何人都可以解释为什么滞后会突然增加吗?
是否有很多commitAsync请求在代理上挂起,也许有一段时间(由代理上的某些配置定义),commitAsync请求开始失败?
假设消费者线程花了max.poll.interval.ms
以上的时间来处理消息。在这种情况下,它将被踢出该组并触发重新平衡。现在,代理上所有待处理的commitAsync
请求都因CommitFailedException
而失败,因为该分区现在属于组中的其他某个使用者。在上面的代码中,使用者将摆脱无限循环,并将永远关闭。这是正确的方法吗?还是我应该抓住CommitFailedException
并再次恢复循环以保持消费者的生命?
答案 0 :(得分:0)
想象一下,我们发送了一个提交偏移量2000的请求。这是一个暂时的通信问题,因此代理从未获得该请求,因此也从未响应。与此同时, 我们处理了另一个批次并成功提交了偏移量3000。现在重试以前的批次失败的提交,并且例外情况下,它会显示相同的消息。在重新平衡的情况下,这将导致重复次数更多
A。滞后时间在增加
由于重新平衡的频率越来越高,因此消费者没有不断使用记录,而生产者却在不断产生记录。
B。 commitAsync请求超时
仅该组的活动成员可以提交偏移量。如果使用者在尝试提交偏移量时已被踢出组,则会抛出CommitFailedException
c。重新平衡
重新平衡开始时,使用者必须在会话超时到期之前完成其当前正在执行的所有处理,提交偏移量并重新加入该组。
我们应该强制使用ConsumerRebalanceListener并使用onPartitionsRevoked()提交偏移,然后再失去对分区的所有权以提交当前偏移。
将max.poll.interval.ms 和 max.poll.records 设置为一个相当低的值,同时也将session.timeout.ms保持为低,这样故障检测时间就不会出现不需要牺牲。
从commitSync()引发的CommitFailedException。这样可以保证只有组中的活动成员才可以提交偏移量。如果使用者已被踢出该组,则其分区将被分配给另一个成员,该成员将提交自己的偏移量。