我不完全了解消费者错误处理如何通过提交offset和akcMode以及如何通过在发生错误时停止容器来影响它(使用 spring-kafka 1.3。* )。
让我们说我有两个使用方(使用两个分区),它们在轮询(max.records.per.poll=5
时都从其分区中获取5个事件。
第一个使用者-处理第一个事件好,处理第二个事件失败-因此在错误处理程序中,我调用kafkaListenerEndpointRegistry.stop()
,但是由于实施了stop,它只是停止了使用者轮询,所以两个使用者仍然完成了其当前处理。批次。因此,第一个使用者处理事件3,4,5(所有事件均已处理且没有错误),并且可以说第二个使用者在第4个事件上失败(事件1,2,3,5被处理正常)。
我的问题是每个消费者将承担哪些补偿?
我的理解是:
AckMode.RECORD/BATCH
与ackOnError
结合使用时-
两个消费者都将获得最新的抵销额(5)AckMode.RECORD/BATCH
与!ackOnError
结合使用时-两个使用者都将提交最新的偏移量-因为尽管在批处理过程中某些事件失败,但批处理中的最新处理事件是可以的,所以最新处理后的事件抵消额获胜。我的理解正确吗?
答案 0 :(得分:3)
您的理解是正确的;当您停止容器时,还应该向侦听器发出信号,告知它也需要拒绝任何剩余的记录,这样就不会提交其偏移量。
我们正在考虑添加一种stopNow()
方法,这将防止其他记录发送到侦听器。
在2.0中,我们添加了RemainingRecordsErrorHandler
(和实现SeekToCurrentErrorHandler
)。当容器检测到这样的错误处理程序时,它将其余记录呈现给错误处理程序而不是侦听器。
SeekToCurrentErrorHandler
将所有主题/分区都查找到未处理的偏移量(包括失败的记录),以便在下一次民意测验中全部检索到它们。
自定义实现可能会查找剩余的记录,但会将失败的记录发送到死信主题(或以其他方式处理)。
也就是说,stopNow()
对于大多数人来说可能更容易处理,但是可能仅是2.2功能; 1.3.x用户需要在失败后丢弃/拒绝未处理的记录。
您还可以使用RetryingMessageListenerAdapter
(如果使用@KafkaListener
则启用重试),这将根据重试配置重试交付,而完全不涉及Kafka。重试用尽并提交偏移量后,可以通过RecoveryCallback
处理失败的记录;在这种情况下,无需停止容器。