【发布时间】:2023-04-09 08:49:01
【问题描述】:
我有这个使用 Spring 实现的 Kafka 消费者:
public class MyKafkaConsumer<T> implements AcknowledgingMessageListener<String, T> {
private final ConcurrentMessageListenerContainer<String, T> container;
public MyKafkaConsumer(ConsumerFactory<String, T> consumerFactoryry) {
ContainerProperties prop = new ContainerProperties("mytopic");
prop.setGroupId("mygroupid");
prop.setMessageListener(this);
prop.setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
this.container = new ConcurrentMessageListenerContainer<>(consumerFactory, prop);
}
@Override
public void onMessage(ConsumerRecord<String, T> record, Acknowledgment acknowledgment) {
// Just log the message, but don't acknowledge
}
}
Kafka 配置了以下两个属性:
isolation.level = read_uncommitted
enable.auto.commit = false
由于我没有调用 acknowledgement.acknowledge(),我希望偏移量不会被提交。我也希望多次收到相同的消息,但这不会发生。当我重新启动整个应用程序时,它只会碰巧收到相同的消息。这是为什么?我不应该多次收到相同的消息吗?
我确定没有提交偏移量,因为我在重新启动应用程序时再次收到该消息。那么,还有什么情况呢?
我注意到,如果我在“onMessage”方法中抛出异常,那么我实际上会多次收到相同的消息。在这种情况下有什么区别?在这两种情况下,偏移量不是以相同的方式提交吗?
【问题讨论】:
-
相当确定行为内置于消费者中,基于此,请查看“偏移量和消费者位置”部分kafka.apache.org/22/javadoc/org/apache/kafka/clients/consumer/…
-
这是有道理的......但是当我抛出异常时有什么不同?因为在那种情况下,我一直收到相同的消息
-
很可能是提供给您的 Consumer 类在调用
onMessage后会更新position值,因此在onMessage中未捕获的异常的情况下,内部位置不会不会更新。 (通常我会查看代码来确认这一点,但还没有找到正确的来源)。如果您只想接收一次消息,即使您在处理过程中遇到异常,您也可以在onMessage内添加一个不会重新抛出的 try/catch。在理想情况下,您会将违规消息扔到另一个队列中以进行手动处理,或者将其记录在某个地方。
标签: java spring apache-kafka