【问题标题】:Spring Kafka- Trying to understand how things work behind the scenesSpring Kafka - 试图了解幕后的工作原理
【发布时间】:2018-06-23 14:12:03
【问题描述】:

考虑以下代码-

@Bean
public ConsumerFactory<String, String> consumerFactory() {
    Map<String, Object> props = new HashMap<>();
    props.put(
      ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, 
      bootstrapAddress);
    props.put(
      ConsumerConfig.GROUP_ID_CONFIG, 
      groupId);
    props.put(
      ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, 
      StringDeserializer.class);
    props.put(
      ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, 
      StringDeserializer.class);
    return new DefaultKafkaConsumerFactory<>(props);
}

@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> 
  kafkaListenerContainerFactory() {

    ConcurrentKafkaListenerContainerFactory<String, String> factory
      = new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());
    return factory;
}

我创建了一个消费者工厂和一个并发 KafkaListenercontainer 工厂。我还没有为监听器工厂设置并发。 我有一个用@KafkaListener 注释的方法

@KafkaListener(topics = "topicName")
public void listen(String message) {
    System.out.println("Received Message: " + message);

当我不设置并发属性时,Spring会创建1个消费者实例,1个kafka监听器容器,属于消费者工厂中指定的组吗?

如果我将并发更改为 3,spring 会创建 3 个消费者实例,因此在配置消费者工厂和 3 个侦听器容器时指定同一消费者组中的 3 个消费者?

另外,根据并发性,假设我们现在只收听一个主题,我们将有 3 个用 @kafkalistener 注释的方法,如果未指定分区,则所有 3 个方法都收听不同的分区(由 kafka 以循环方式提供)。 ?

我是 Kafka 的新手,想澄清一下我的理解。

【问题讨论】:

    标签: java spring spring-kafka


    【解决方案1】:

    当我不设置并发属性时,Spring会创建1个消费者实例,1个kafka监听器容器,属于消费者工厂中指定的组吗?

    您将有一个消费者从该主题的所有分区中获取事件。

    如果我将并发更改为 3,spring 会创建 3 个消费者实例,因此在配置消费者工厂和 3 个侦听器容器时指定同一消费者组中的 3 个消费者?

    您将拥有 3 个消费者实例,如果您在该主题中至少有 3 个分区,则每个分区都会从其中一个分区中获取事件。消费者将事件传递给该 KafkaListener 实例。

    你可以更具体。

    @KafkaListener(
      topicPartitions = @TopicPartition(topic = "topicName",
      partitionOffsets = {
        @PartitionOffset(partition = "0", initialOffset = "0"), 
        @PartitionOffset(partition = "3", initialOffset = "0")
    }))
    public void listenToParition(
      @Payload String message, 
      @Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition) {
          System.out.println(
            "Received Messasge: " + message"
            + "from partition: " + partition);
    }
    

    另外,根据并发性,假设我们现在只收听一个主题,我们将有 3 个用 @kafkalistener 注释的方法,如果未指定分区,则所有 3 个方法都收听不同的分区(由 kafka 以循环方式提供)。 ?

    这毫无意义。首先,KafkaListeners 是 Spring Kafka 的高级抽象,Kafka 根本不会轮询(从消费者的角度来看,它与生产者不同),如果你有 3 个消费者(相同的消费者组+监听同一个主题),以及主题中的 3 个分区,Kafka 将重新平衡并将一个分区分配给一个消费者,每个消费者将仅从 Kafka 分配的分区中获取事件。 Spring Kafka 在收到每个消费者的事件后,会在 KafkaListener 实例中传递事件。

    【讨论】:

    • howtoprogram.xyz/2016/09/25/… 你如何评价这篇文章 Dani?我的理解就是基于此。
    • 另外,我的最后一个问题没有恰当地框定?但这就是我想说的,并发 3 所以 3 个使用者实例,每个实例从一个主题的 3 个分区之一中获取,并将消息提供给一个侦听器容器(每个使用者实例都有一个),这会将其提供给一个方法总共 3 个用 @kafkaListener 注释..
    • 如果您有 3 个@KafkaListener,他们将分别从配置的主题中分配分区。如果他们有相同的主题和不同的group.id,他们将各自获得每条消息的副本。如果它们具有相同的group.id,并且正在使用组管理,则 Kafka 将在实例之间分发主题/分区。如果每个topic只有1个partition,不保证每个topic都会得到1个partition;最有可能的是,一个实例将获得每个主题的单个分区,而另外 2 个实例将处于空闲状态。
    • 最后一个问题,是在kafka服务器上注册的group id还是只对consumer端有意义?如果我有两个应用程序部署在 2 台不同的机器上。在每个应用程序中,我都有一个侦听器,并且消费者工厂已配置相同的组 ID,2 台不同机器上的两个侦听器是否成为同一消费者组的一部分?
    • 没错。这是 Apache Kafka 中 consumer group 功能的规范目的。同一组的所有消费者都在 Broker 上注册并被视为成员,当只有一个消费者可以访问每个分区时。请阅读更多 Kafka 文档
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2017-09-20
    • 1970-01-01
    相关资源
    最近更新 更多