情况
我正在尝试为Spring-Kafka(2.3.3.RELEASE)批处理消息侦听器实现自定义错误处理程序。我的骨骼配置非常裸露:
val factory = ConcurrentKafkaListenerContainerFactory<Int, String>()
factory.consumerFactory = kafkaConsumerFactory
factory.isBatchListener = true
factory.setBatchErrorHandler(MyErrorHandler())
没有任何额外的使用者配置。请注意,“从2.3版开始,框架将enable.auto.commit设置为false”。
我使用的是“消费者意识” @KafkaListener
,我的自定义错误处理程序也实现了ConsumerAwareBatchErrorHandler
。
在我的错误处理程序中,我使用Consumer.seek(topicPartition, offset)
方法来寻找下一个或寻找当前的偏移量。
问题是,每当调用错误处理程序并手动寻找某个偏移量时,该偏移量似乎都不会提交给Kafka。通过以下事实证明了这一点:在应用程序重新启动后,它轮询相同的(以前是失败的)记录(即使当代码寻求下一个记录时)。
更令我困惑的是,在应用程序运行时,它似乎确实使用了seek()
偏移量并轮询 new 记录。
我尝试使用不同的AckMode
,例如MANUAL
或MANUAL_IMMIDIATE
,但这不会改变观察到的行为。此外,文档还说明了这些模式:
MANUAL和MANUAL_IMMEDIATE要求侦听器为AcknowledgingMessageListener或BatchAcknowledgingMessageListener
显然我没有用。
如果已经找到一个“修订”,则在consumer.commitSync()
之后调用.seek()
,该修订似乎立即提交了偏移量。日志记录也对此进行了备份:
DEBUG 13784 --- [ntainer#2-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator : [Consumer clientId=consumer-1, groupId=kafka-retry-test] Committed offset 28 for partition test-retry-batch-custom-e-0
问题
为什么只调用consumer.seek(...)
而不向kafka提交偏移量,我是否缺少一些关键配置?调用.commitSync()
似乎是一种技巧,文档中没有描述它在任何地方都不需要。
答案 0 :(得分:1)
搜索不提交偏移量,它只是将当前使用者定位在该点上。您需要致电df['flag'] = df['flag'].mask(df['days'].isna(), df['flag'].ffill())
print (df)
date flag days
0 01/01/2019 start 1.0
1 01/02/2019 start NaN
2 01/03/2019 start NaN
3 01/04/2019 end NaN
4 01/05/2019 end NaN
5 01/06/2019 end NaN
6 01/07/2019 start NaN
7 01/08/2019 NaN 2.0
8 01/09/2019 start NaN
9 01/10/2019 start NaN
或syncCommit
。
但是,从版本2.3.3(当前版本为2.3.4)开始,您可以从asyncCommit
返回true:
isAckAfterHandle()
,容器将为您完成提交。
从版本2.3.2开始,这些接口具有默认方法
/** * Return true if the offset should be committed for a handled error (no exception * thrown). * @return true to commit. * @since 2.3.2 */ default boolean isAckAfterHandle() { // TODO: Default true in the next release. return false; }
,容器将调用该方法以确定是否在错误处理程序返回而未引发异常的情况下提交偏移量。为了向后兼容,默认情况下返回false。但是,在大多数情况下,我们希望应提交偏移量。例如,如果恢复了记录,则SeekToCurrentErrorHandler返回true(在任何重试之后,如果已配置)。在将来的版本中,我们希望将此默认值更改为true。
但是,如果您使用的是手动确认,则错误处理程序必须手动提交。