为消费者组中的Apache Beam KafkaIO消费者分配了唯一的组ID

时间:2020-07-20 17:58:03

标签: apache-beam apache-beam-kafkaio

我正在使用DirectRunner运行apache Beam KafkaIO的多个实例,它们是从同一主题中读取的。但是消息正在传递到所有正在运行的实例。看到我发现的Kafka配置后,组名将附加一些唯一的前缀,并且每个实例都有唯一的组名。

  1. group.id = Reader-0_offset_consumer_559337182_ my_group
  2. group.id = Reader-0_offset_consumer_559337345_ my_group

因此,每个实例都有唯一的 group.id 分配,这就是为什么将消息传递到所有实例的原因。

pipeline.apply("ReadFromKafka", KafkaIO.<String, String>read().withReadCommitted()
            .withConsumerConfigUpdates(
                    new ImmutableMap.Builder<String, Object>().put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true)
                            .put(ConsumerConfig.GROUP_ID_CONFIG, "my_group")
                            .put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 5).build())
            .withKeyDeserializer(StringDeserializer.class).withValueDeserializer(StringDeserializer.class)
            .withBootstrapServers(servers).withTopics(Collections.singletonList(topicName)).withoutMetadata()

那我必须给什么配置,以使组中的所有使用者都不会阅读相同的消息

1 个答案:

答案 0 :(得分:0)

是的,这是因为组名被附加了一些唯一的前缀,并且每个实例都有唯一的组名。因此,kafka不知道您是否再启动一个实例。因此,相同的消息将传递给所有消费者。

因此,我能想到的一种解决方法是代替给出主题并让Beam确定所有分区的使用者数量,您可以使用DirectRunner为Apache Beam KafkaIO的每个实例显式给出主题分区。

您将必须将List类型的TopicPartition传递给方法withTopicPartitions

KafkaIO.<String, String>read()
                .withCreateTime(Duration.standardMinutes(1))
                .withReadCommitted()
                .withBootstrapServers(endPoint)
                .withConsumerConfigUpdates(new ImmutableMap.Builder<String, Object>()
                        .put(ConsumerConfig.GROUP_ID_CONFIG, groupName)
                        .put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 5)
                        .put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest")
                        .build())
                .withTopicPartitions(Arrays.asList(new TopicPartition(topicName, 0)))
                .withKeyDeserializer(StringDeserializer.class)
                .withValueDeserializer(StringDeserializer.class)
                .withoutMetadata();

上面的代码将仅从partition 0中读取消息。因此,通过这种方式,您可以旋转同一程序的多个实例,而不会将相同的消息传递给所有使用者

相关问题