Java Spring Kafka模板生成器在代理重新启动时丢失消息
我将SpringBoot(2.1.6.RELEASE)与SpringKafka(2.2.7.RELEASE)一起使用,并使用KafkaTemplate向我的kafka集群发送消息。但有时(通常在我重新启动kafka代理或进行重新平衡时),我在发送消息时会看到如下错误:Java Spring Kafka模板生成器在代理重新启动时丢失消息,java,spring-boot,apache-kafka,spring-kafka,kafka-producer-api,Java,Spring Boot,Apache Kafka,Spring Kafka,Kafka Producer Api,我将SpringBoot(2.1.6.RELEASE)与SpringKafka(2.2.7.RELEASE)一起使用,并使用KafkaTemplate向我的kafka集群发送消息。但有时(通常在我重新启动kafka代理或进行重新平衡时),我在发送消息时会看到如下错误: org.apache.kafka.common.errors.NotLeaderForPartitionException: This server is not the leader for that topic-partiti
org.apache.kafka.common.errors.NotLeaderForPartitionException: This server is not the leader for that topic-partition.
由于默认的Kafka producer配置,我希望可以重试发送失败,但不会。默认卡夫卡制作人配置:
retries: 2147483647 (https://kafka.apache.org/documentation/#retries)
acks: 1 (https://kafka.apache.org/documentation/#acks)
我的配置如下:
@Bean
public Map<String, Object> producerConfigs()
{
// See https://kafka.apache.org/documentation/#producerconfigs for more properties
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "gzip");
return props;
}
@Bean
public ProducerFactory<Long, String> producerFactory()
{
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
@Bean
public KafkaTemplate<Long, String> kafkaTemplate(KafkaTemplateProducerListener<Long, String> kafkaTemplateProducerListener,
ProducerFactory<Long, String> producerFactory)
{
KafkaTemplate<Long, String> kafkaTemplate = new KafkaTemplate<>(producerFactory);
kafkaTemplate.setProducerListener(kafkaTemplateProducerListener);
return kafkaTemplate;
}
我已经在互联网上搜索过了,每个人都说这种带有重试和确认的配置必须有效,但它没有。我错过了什么
谢谢在花了一些时间调试之后,我找到了解决方案:
props.put(ProducerConfig.ACKS_CONFIG, "all");
有关此属性的详细信息:
非常好的博客,展示了在卡夫卡中可能丢失消息的不同场景:
- 第1部分:
- 第2部分:
旁注-从答案中我发现,如果您不想在关机时丢失消息,最好使用此选项:
@PreDestroy
public void flush()
{
kafkaTemplate.flush();
}
@PreDestroy
public void flush()
{
kafkaTemplate.flush();
}