Kafka,Spring Kafka和重新传递旧消息

时间:2018-07-08 09:29:07

标签: spring-boot apache-kafka spring-kafka

我将Kafka和Spring Boot与Spring Kafka一起使用。在异常终止应用程序并重新启动之后,我的应用程序开始从Kafka队列接收旧的,已处理的消息。

这可能是什么原因以及如何查找和解决问题?

我的Kafka属性:

spring.kafka.bootstrap-servers=${kafka.host}:${kafka.port}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.group-id=postfenix
spring.kafka.consumer.enable-auto-commit=false

我的Spring Kafka工厂和收听者:

@Bean
public ConcurrentKafkaListenerContainerFactory<String, Post> postKafkaListenerContainerFactory(KafkaProperties kafkaProperties) {

    ConcurrentKafkaListenerContainerFactory<String, Post> factory = new ConcurrentKafkaListenerContainerFactory<>();
    factory.getContainerProperties().setAckMode(AckMode.MANUAL);
    factory.setConsumerFactory(postConsumerFactory(kafkaProperties));

    return factory;
}

@KafkaListener(topics = "${kafka.topic.post.send}", containerFactory = "postKafkaListenerContainerFactory")
public void sendPost(ConsumerRecord<String, Post> consumerRecord, Acknowledgment ack) {

    Post post = consumerRecord.value();

    // do some logic here

    ack.acknowledge();
}

1 个答案:

答案 0 :(得分:4)

使用Kafka时,客户端需要自己提交偏移量。这与其他消息代理(例如AMQP代理)相反,在该代理中,代理跟踪客户端已收到的消息。

在您的情况下,您不会自动提交偏移,因此Kafka希望您手动提交偏移(由于此设置:spring.kafka.consumer.enable-auto-commit=false)。如果您没有在程序中手动提交偏移量,那么您描述的行为几乎就是预期的行为。 Kafka根本不知道您的程序成功处理了哪些消息。每次您重新启动程序时,Kafka都会看到您的程序尚未提交任何偏移量,并将应用您在spring.kafka.consumer.auto-offset-reset=earliest中提供的策略,这意味着队列中的第一条消息。

如果这对您来说是新事物,我建议您阅读关于this的Kafka文档和this Spring文档,因为Kafka与其他消息代理完全不同。