Kafka:同一使用者组中的多个实例正在侦听主题内的同一分区

时间:2018-09-13 14:55:53

标签: spring-boot apache-kafka kafka-consumer-api spring-kafka

我有两个kafka使用者实例,配置了相同的使用者组并在同一主题中侦听分区0。问题是当我向该主题发送消息时。该消息由两个实例使用,这两个实例应该不会发生,因为它们在同一组中。 我正在使用Spring Boot配置类来配置它们。

这是配置:

@Bean
ConcurrentKafkaListenerContainerFactory<Integer, String> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<Integer, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());
    factory.getContainerProperties().setAckMode(AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIATE);
    return factory;
}

@Bean
public ConsumerFactory<Integer, String> consumerFactory() {
    return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}

@Bean
public Map<String, Object> consumerConfigs() {

    Map<String, Object> props = new HashMap<>();
    props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
    props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupId);
    props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
    props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "100");
    props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "15000");
    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, keyDeserializer);
    props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, valueDeserializer);
    props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
    return props;
}

这是听众:

@KafkaListener(topicPartitions = {@TopicPartition(topic = "${kafka.topic.orders}", partitions = "0")})
public void consume(ConsumerRecord<String, String> record, Acknowledgment acknowledgment) {

    log.info("message received at " + orderTopic + "at partition 0");
    processRecord(record, acknowledgment);
}

1 个答案:

答案 0 :(得分:2)

Kafka不能那样工作;当您手动分配这样的分区(@TopicPartition)时,您明确告诉Kafka您要从该分区接收消息-使用者assign()将分区分配给自己。

换句话说,通过手动分配,您将负责分配分区。

您需要使用组管理,然后让Kafka将主题分配给实例。

使用topics = "...",Kafka将完成分配。如果您没有足够的主题,实例将处于空闲状态。要使所有实例都参与,至少需要与实例一样多的分区。