我正在使用spring boot + spring @KafkaListener。我期望的行为是:我的kafka侦听器读取10个线程中的消息。这样,如果其中一个线程挂起,则其他消息将继续读取和处理消息。
我定义的
@Bean
public ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory(
ConcurrentKafkaListenerContainerFactoryConfigurer configurer,
ConsumerFactory<Object, Object> kafkaConsumerFactory)
{
ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
configurer.configure(factory, kafkaConsumerFactory);
factory.getContainerProperties().setMissingTopicsFatal(false);
factory.getContainerProperties().setCommitLogLevel(LogIfLevelEnabled.Level.INFO);
return factory;
}
和spring boot配置:
spring.kafka.listener.concurrency=10
我看到所有配置都能正常工作,我在jmx中看到了10个线程:
但是我进行了这样的测试:
@KafkaListener(topics = {
"${topic.name}" }, clientIdPrefix = "${kafka.client.id.prefix}", idIsGroup = false, id = "${kafka.listener.name}", containerFactory = "kafkaListenerContainerFactory")
public void listen(ConsumerRecord<String, String> record)
{
if(record.getVersion() < 3) {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
System.out.println("It works!");
}
如果版本是<3,则挂起,否则-运行。 我发送了1,2和3版本的3条消息。我希望版本1和2的消息会挂起,但是版本3将在侦听器时处理。但是不幸的是,版本3的消息在开始处理之前会等待消息1和2。
也许我的期望不是真的,这是kafka监听器的正确行为。 请帮助我处理kafka并发,为什么会这样呢?
答案 0 :(得分:3)
Kafka不能那样工作;您至少需要与使用者一样多的分区(由spring容器中的concurrency
控制)。
此外,一次(组中)只有一个使用者(一次使用)可以从一个分区中进行使用,因此,即使您增加了分区,在“卡住”的使用者之后的同一分区中的记录也不会被其他使用者接收。 / p>
答案 1 :(得分:1)
如果要对Kafka进行故障转移,则必须打开应用程序的更多实例。
示例:您有一个名为test的主题,带有1个分区,您将使用相同的Kafka组创建应用程序的2个实例。一个实例将处理您的数据,另一个实例将在第一次实例崩溃时等待并开始处理消息。如果您有N个分区,其中N个分区具有应用程序的N + 1或2或3个实例,则相同。同样,每个实例只有一个使用者线程。
有关在Google上进行搜索的更多信息: Kafka消费者群体。