Java 如何使用Spring提供的Kafka API在消费组中创建多个消费者

Java 如何使用Spring提供的Kafka API在消费组中创建多个消费者,java,apache-kafka,spring-kafka,Java,Apache Kafka,Spring Kafka,我正在尝试在一个消费者组中创建多个消费者,以便进行并行处理,因为我们有大量的消息流入。我使用的是spring boot和KafkTemplate。如何在spring boot应用程序的单个实例中创建属于单个使用者组的多个使用者? 使用@KafkaListener注释多个方法是否会创建多个使用者?您必须使用ConcurrentMessageListenerContainer。它委托给一个或多个KafkaMessageListenerContainer实例以提供多线程消费 @Bean KafkaLi

我正在尝试在一个消费者组中创建多个消费者,以便进行并行处理,因为我们有大量的消息流入。我使用的是spring boot和KafkTemplate。如何在spring boot应用程序的单个实例中创建属于单个使用者组的多个使用者?
使用@KafkaListener注释多个方法是否会创建多个使用者?

您必须使用
ConcurrentMessageListenerContainer
。它委托给一个或多个
KafkaMessageListenerContainer
实例以提供多线程消费

@Bean
KafkaListenerContainerFactory KafkaListenerContainerFactory(){
ConcurrentKafkalistener集装箱工厂=
新的ConcurrentKafkaListenerContainerFactory();
setConsumerFactory(consumerFactory());
工厂设置并发(10);
factory.getContainerProperties().setPollTimeout(3000);
返回工厂;
}
setConcurrency(10)创建10个
KafkaMessageListenerContainer
实例。每个实例都会获得一定数量的分区。这取决于创建主题时配置的分区数

一些准备步骤:

@Autowired
私人卡夫卡模板卡夫卡模板;
私有最终静态字符串引导\u ADDRESS=“localhost:9092”;
私有最终静态字符串CONSUMER\u GROUP=“CONSUMER-GROUP-1”;
私有最终静态字符串TOPIC=“测试主题”;
@豆子
公共消费者工厂消费者工厂(){
Map props=newhashmap();
put(ConsumerConfig.BOOTSTRAP\u server\u CONFIG,BOOTSTRAP\u ADDRESS);
props.put(ConsumerConfig.GROUP\u ID\u CONFIG,CONSUMER\u GROUP);
put(ConsumerConfig.KEY\u反序列化程序\u类\u配置,StringDeserializer.CLASS);
put(ConsumerConfig.VALUE\u反序列化程序\u类\u配置,StringDeserializer.CLASS);
返回新的默认卡夫卡消费工厂(道具);
}
@KafkaListener(topics=TOPIC,containerFactory=“kafkaListenerContainerFactory”)
public void listen(@Payload String message){
logger.info(消息);
}
公开作废开始(){
试一试{
线程。睡眠(5000L);
}捕捉(中断异常e){
e、 printStackTrace();
}
对于(int i=0;i<10;i++){
kafkaTemplate.send(主题,i,字符串,valueOf(i),“消息”+i);
}
logger.info(“发送所有消息”);
}
如果运行上面的方法,您可以看到每个
KafkaMessageListenerContainer
实例处理放入该实例所服务的分区中的消息。 添加Thread.sleep()以等待使用者初始化

2020-07-01 15:48:34.800信息201566---[ntainer#0-4-C-1]r.s.C.Kafkaconsumers演示:信息5
2020-07-01 15:48:34.801信息201566---[ntainer#0-6-C-1]r.s.C.Kafkaconsumers演示:信息7
2020-07-01 15:48:34.800信息201566---[ntainer#0-7-C-1]r.s.C.卡夫卡消费者演示:信息8
2020-07-01 15:48:34.800信息201566---[ntainer#0-9-C-1]r.s.C.Kafkaconsumers演示:信息1
2020-07-01 15:48:34.800信息201566---[ntainer#0-0-C-1]r.s.C.Kafkaconsumers演示:消息0
2020-07-01 15:48:34.800信息201566---[ntainer#0-8-C-1]r.s.C.卡夫卡消费者演示:信息9
2020-07-01 15:48:34.800信息201566---[ntainer#0-3-C-1]r.s.C.卡夫卡消费者演示:信息4
2020-07-01 15:48:34.801信息201566---[ntainer#0-2-C-1]r.s.C.Kafkaconsumers演示:信息3
2020-07-01 15:48:34.801信息201566---[ntainer#0-1-C-1]r.s.C.Kafkaconsumers演示:信息2
2020-07-01 15:48:34.800信息201566---[ntainer#0-5-C-1]r.s.C.卡夫卡消费者演示:信息6

是的,
@KafkaListener
将为您创建多个消费者

有了它,您可以将它们配置为使用同一主题并属于同一组。 Kafka协调员将向您的消费者分发分区

尽管在主题中只有一个分区,但并发不会发生:单个分区在单个线程中处理


另一个选项确实是配置一个
并发
,然后再根据
并发分区
状态创建几个消费者。

正如@Salavat Yalalo所建议的那样,我将我的卡夫卡容器工厂设置为
ConcurrentKafkaListenerContainerFactory
。在@kafkalistener方法上,我添加了一个名为concurrency的选项,该选项接受一个整数作为字符串,表示要跨越的使用者数量,如下所示

@KafakListener(concurrency ="4", containerFactory="concurrentKafkaListenerContainerFactory(bean name of the factory)",..other optional values)
public void topicConsumer(Message<MyObject> myObject){
//.....
}
@KafakListener(concurrency=“4”、containerFactory=“concurrentkafkafkalistenercontainerfactory(工厂的bean名称)”,…其他可选值)
公共无效主题消费者(消息myObject){
//.....
}

运行时,我看到在单个消费者组中创建了4个消费者。

是的,@KafkaListener将为您创建多个消费者。
。如果这是你的意思的话,快速检查确实表明存在一个元素。无论如何,谢谢你,阿泰姆!谢谢你@Salavat Yalalo!我可以创建多个消费者,但我们如何知道哪个消费者处理/阅读了主题中的信息?日志中是否会打印任何消费者id?我在您的回答中看到“[ntainer#0-5-C-1]”,我假设在日志中的某个地方打印了消费者id(如果存在)。如果是,你能给我看看吗?