Kafka Spring:如何动态或循环创建监听器?

时间:2018-12-10 23:32:00

标签: spring-kafka

我有4个ConsumerFactory侦听器,它们正在从4个不同的主题中进行读取,例如:

@KafkaListener(
      id = "test1",
      topicPattern  = "test.topic1",
      groupId = "pp-test1")
  public void listenTopic1(ConsumerRecord<String, String> record) {
    System.out.println("Topic is: " + record.topic());   
  }

但是我们将有50个主题,我希望设置至少25个监听器以实现更好的性能。如何动态执行此操作,而不是手动编写25个侦听器?

2 个答案:

答案 0 :(得分:2)

您不能以编程方式创建@KafkaListener,只能创建离散的侦听器容器(带有自定义侦听器)。

您可以通过编程为每个侦听器创建子应用程序上下文来实现。

编辑

@SpringBootApplication
public class So53715268Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(So53715268Application.class, args);
        for (int i = 0; i < 2; i++) {
            AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
            child.setParent(context);
            child.register(ChildConfig.class);
            Properties props = new Properties();
            props.setProperty("group", "group." + i);
            props.setProperty("topic", "topic" + i);
            PropertiesPropertySource pps = new PropertiesPropertySource("listenerProps", props);
            child.getEnvironment().getPropertySources().addLast(pps);
            child.refresh();
        }
    }

}

@Configuration
@EnableKafka
public class ChildConfig {

    @Bean
    public Listener listener() {
        return new Listener();
    }

}

public class Listener {

    @KafkaListener(id = "${group}", topics = "${topic}")
    public void listen(String in) {
        System.out.println(in);
    }

}

: partitions assigned: [topic0-0]
: partitions assigned: [topic1-0]

请注意,如果您使用的是Spring Boot,则子配置类和侦听器必须位于与主应用程序不同的包中(也不是子包)。

答案 1 :(得分:0)

比方说,您的监听器方法是Springboot应用程序的一部分,该应用程序称为监听器。从配置应用程序yml中读取主题名称:

@KafkaListener(
  topics = "${ai.kafka.consumer.topic-name}")
public void listenTopic1(ConsumerRecord<String, String> record) {
System.out.println("Topic is: " + record.topic());   
}

然后根据需要部署尽可能多的侦听器,每个侦听器在application.yml中具有不同的topic-name值。 (如果您使用的是Docker容器,那会更容易)。