如何在@KafkaListeners中将groupId设置为null

时间:2019-05-13 14:18:51

标签: apache-kafka spring-kafka

与:this question

我正在尝试通过@KafkaListener阅读一个紧凑的主题。 我希望每个消费者每次都阅读整个主题。

我无法为每个使用者分别生成唯一的groupId。所以我想使用一个空的groupid。

我尝试将容器和使用者配置为将groupId设置为null,但是都无效。

这是我的容器配置:

 ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
        configurer.configure(factory, kafkaConsumerFactory);
        // Set ackMode to manual and never commit, we are reading from the beginning each time
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL);
        factory.getContainerProperties().setAckOnError(false);
        // Remove groupId, we are consuming all partitions here
        factory.getContainerProperties().setGroupId(null);
        // Enable idle event in order to detect when init phase is over
        factory.getContainerProperties().setIdleEventInterval(1000L);

还尝试强制使用方配置:

Map<String, Object> consumerProperties = sprinfKafkaProperties.buildConsumerProperties();
        // Override group id property to force "null"
        consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, null);
        ConsumerFactory<Object, Object> kafkaConsumerFactory = new DefaultKafkaConsumerFactory<>(consumerProperties);

当我将容器groupId设置为null时,将使用具有侦听器ID的默认值。

当我将使用者强制为空的groupId属性时,出现错误: 在使用者配置,容器属性或@KafkaListener批注中找不到group.id;使用组管理时,需要一个group.id。

1 个答案:

答案 0 :(得分:1)

您不能使用空的group.id

来自kafka documentation

group.id

  

一个唯一字符串,用于标识此消费者所属的消费者组。如果消费者通过使用subscription(topic)或基于Kafka的偏移量管理策略来使用组管理功能,则必需该属性。

如果您希望每次都从头开始阅读,则可以将ConsumerAwareRebalanceListener添加到容器工厂,也可以使监听器实现ConsumerSeekAware

在任何一种情况下,当调用onPartitionsAssigned时,都应从头到尾查找每个主题/分区。

  

我无法为每个使用者分别生成唯一的groupId。

您可以使用SpEL表达式生成UUID。

编辑

您可以手动分配主题/分区,然后group.id可以为null。

@SpringBootApplication
public class So56114299Application {

    public static void main(String[] args) {
        SpringApplication.run(So56114299Application.class, args);
    }

    @Bean
    public NewTopic topic() {
        return new NewTopic("so56114299", 10, (short) 0);
    }

    @KafkaListener(topicPartitions = @TopicPartition(topic = "so56114299",
                          partitions = "#{@finder.partitions('so56114299')}"))
    public void listen(@Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) String key, String payload) {
        System.out.println(key + ":" + payload);
    }

    @Bean
    public PartitionFinder finder(ConsumerFactory<String, String> consumerFactory) {
        return new PartitionFinder(consumerFactory);
    }

    public static class PartitionFinder {

        public PartitionFinder(ConsumerFactory<String, String> consumerFactory) {
            this.consumerFactory = consumerFactory;
        }

        private final ConsumerFactory<String, String> consumerFactory;

        public String[] partitions(String topic) {
            try (Consumer<String, String> consumer = consumerFactory.createConsumer()) {
                return consumer.partitionsFor(topic).stream()
                    .map(pi -> "" + pi.partition())
                    .toArray(String[]::new);
            }
        }

    }

}

spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.listener.ack-mode=manual