繁体   English   中英

如何有效地将我的@KafkaListener 绑定到 ConcurrentKafkaListenerContainerFactory?

[英]How can I effectively bind my @KafkaListener to ConcurrentKafkaListenerContainerFactory?

我遇到了这个对我来说很奇怪的场景:

所以基本上我在一个 class 中定义了两个@KafkaListener

@KafkaListener(id = "listener1", idIsGroup = false, topics = "data1", containerFactory = "kafkaListenerContainerFactory")
    public void receive(){}

@KafkaListener(id = "listener2", idIsGroup = false, topics = "data2", containerFactory = "kafkaListenerContainerFactory2")
    public void receive(){}

它们的idtopicscontainerFactory是不同的,并且它们每个都依赖于另一个 class 中定义的不同ConcurrentKafkaListenerContainerFactory

@Bean
public ConcurrentKafkaListenerContainerFactory<String, ConsumerRecord> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, ConsumerRecord> factory = new ConcurrentKafkaListenerContainerFactory();
    factory.setConsumerFactory(consumerFactory("group1", "earliest"));
    factory.setAutoStartup(false);
    return factory;
}

@Bean
public ConcurrentKafkaListenerContainerFactory<String, ConsumerRecord> kafkaListenerContainerFactory2() {
    ConcurrentKafkaListenerContainerFactory<String, ConsumerRecord> factory = new ConcurrentKafkaListenerContainerFactory();
    factory.setConsumerFactory(consumerFactory("group2", "latest"));
    factory.setAutoStartup(true);
    return factory;
}

@Bean
public ConsumerFactory<String, ConsumerRecord> consumerFactory(String groupId, String offset) {
    Map<String, Object> config = new HashMap<>();
    // dt is current timestamp in millisecond (epoch)
    config.put(ConsumerConfig.GROUP_ID_CONFIG, groupId + "-" + dt);
    config.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, offset);
    // other config omitted
    return new DefaultKafkaConsumerFactory<>(config);
}

所以我期望看到(以及我想要实现的)是:

  1. 只有 listener2 会自动启动,因为factory.setAutoStartup(true)
  2. Listener2 将以group.id "group2" 和auto.offset.reset "latest" 开头
  3. 稍后,当 listener1 通过某个事件侦听器启动时,它将以group.id "group1" 和auto.offset.reset "earlist" 开头

但是,实际上只保证了第一个。 Listener2 可以以 {group2 + latest} 或 {group1 + early} 开头。 后来当 listener1 开始消费数据时,它只会重用 listener2 的配置(我可以看到包含时间戳的相同组 id 在我的日志中打印了两次)

我的问题是,为什么 listener2 的组 ID 和偏移配置是随机选择的,而 autoStartup 不是? 为什么 listener1 会重用 listener2 的配置?

这是因为consumerFactory是 singleton @Bean并且 arguments 在第二次调用中被忽略。

在工厂中添加@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)每次都会得到一个新的bean。

但是,您不需要任何这些,您可以简单地在注释上设置groupId属性并避免所有这些额外的定义。

您还可以控制注解上的autoStartup (从 2.2 开始)。

编辑

要回答下面评论中的问题...

groupId = "#{'${group.id}' + T(java.time.Instant).now().toEpochMilli()}"

但是,如果您想要一个唯一的组 ID; 这个比较靠谱。。。

groupId = "#{'${group.id}' + T(java.util.UUID).randomUUID()}"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM