我有一个spring-kafka使用者,它读取记录并将它们移交给缓存。计划任务将定期清除缓存中的记录。我只想将一批成功保存在数据库中之后才更新COMMIT OFFSET。我尝试将确认对象传递给缓存服务,以调用确认方法,如下所示。
public class KafkaConsumer {
@KafkaListener( topicPattern = "${kafka.topicpattern}", containerFactory = "kafkaListenerContainerFactory" )
public void receive( ConsumerRecord<String, String> record, Acknowledgment acknowledgment ) {
cacheService.add( record.value(), acknowledgment );
}
}
public class CacheService {
// concurrency handling has been left out in favor of readability
public void add( String record, Acknowledgment acknowledgment ) {
this.records.add(record);
this.lastAcknowledgment = acknowledgment;
}
public void saveBatch() { //called by scheduled task
if( records.size() == BATCH_SIZE ) {
// perform batch insert into database
this.lastAcknowledgment.acknowledge();
this.records.clear();
}
}
}
AckMode设置如下:
factory.getContainerProperties().setAckMode( AbstractMessageListenerContainer.AckMode.MANUAL );
自动提交为假:
config.put( ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false );
即使调用了确认方法,提交偏移也不会更新。保留记录后更新提交偏移量的最佳方法是什么?
我正在使用spring-kafka 2.1.7.RELEASE。
编辑:@GaryRussell confirmed在下一次轮询期间由消费方线程执行了由外来线程做出的确认后,我重新检查了代码,并发现了上次确认的方式中的错误对象已设置。 修复此问题后,提交偏移量已按预期更新。因此,此问题已解决。但是,我无法将这个问题标记为已回答。
答案 0 :(得分:3)
这是问题所在,使用者线程负责提交偏移量。在轮询时,消费者线程将提交先前的批次偏移量。
因为在您的情况下,AUTO_COMMIT
为假,lastAcknowledgment.acknowledge()
未确认偏移量未提交。
执行此操作的唯一方法是,只要获得轮询记录,就将Schedule
的任务设置为Async
并持有使用者线程并在异步任务完成后提交偏移量,请检查此答案是否为参考answer
注意:如果您持有使用方线程超过5分钟,则会进行here
重新平衡新的Java Consumer现在支持从后台线程进行心跳。有一个新的配置max.poll.interval.ms,它控制使用者调用前主动离开组(默认为5分钟)之前两次轮询之间的最长时间。配置request.timeout.ms的值必须始终大于
max.poll.interval.ms
,因为这是使用者重新平衡时JoinGroup请求可以在服务器上阻止的最长时间,因此我们将其默认值更改为5分钟以上最后,session.timeout.ms
的默认值已调整为10秒,max.poll.records
的默认值已更改为500。
特别说明,来自春季卡夫卡> 2.1.5
对下一个外来线程的确认将在下一次民意调查之前由消费者线程执行。感谢@Gary Russell的信息