1. 引言
在这个教程中,我们将澄清Apache Kafka中GroupId
和ConsumerId
的区别,这对于理解如何正确设置消费者至关重要。此外,我们还将探讨ClientId
与ConsumerId
之间的差异,并了解它们之间的关系。
2. 消费者组
在深入了解标识符类型之前,让我们先理解消费者组的概念。
消费者组由多个协同工作以从一个或多个主题消费消息的消费者组成,实现了并行消息处理。 它们在分布式Kafka环境中支持可扩展性、容错性和消息处理的高效并行。
关键的是,组内每个消费者仅负责处理其主题的一部分,即分区。
3. 识别符理解
接下来,让我们从高层次上定义本教程中涉及的所有标识符:
-
GroupId
唯一标识一个消费者组。 -
ClientId
唯一标识传递给服务器的请求。 -
ConsumerId
分配给消费者组内的单个消费者,它是client.id
消费者属性和消费者唯一标识的组合。
4. 标识符的目的
接下来,让我们理解每个标识符的目的。
GroupId
是负载均衡机制的核心,它使得分区能在消费者之间进行分配。 消费者组管理同一组内消费者的协调、负载平衡和分区分配。Kafka确保在任何给定时间只有一个消费者访问每个分区。如果组内消费者失败,Kafka会无缝地将分区重新分配给其他消费者,以保持消息处理的连续性。
Kafka使用ConsumerId
来确保组内每个消费者与Kafka代理交互时具有唯一标识。 这个完全由Kafka管理的标识符用于管理消费者偏移量和跟踪分区消息处理进度。
最后,ClientId
通过允许开发者配置逻辑应用程序名称,从而追踪请求的来源,而不仅仅是IP/端口。 因为我们可以控制这个值,我们可以创建具有相同ClientId
的两个独立客户端。然而,在这种情况下,Kafka生成的ConsumerId
会不同。
5. 配置GroupId和ConsumerId
5.1. 使用Spring Kafka
在Spring Kafka中,我们可以通过@KafkaListener
注解为消费者定义GroupId
和ConsumerId
:
@KafkaListener(topics = "my-topic", groupId = "my-consumer-group", clientIdPrefix = "my-app")
public void listen(String message) {
// ...
}
请注意,我们指定了groupId
属性为自选的一个值。
此外,我们设置了clientIdPrefix
属性包含一个自定义前缀。让我们检查应用日志,确认ConsumerId
中包含了这个前缀:
@KafkaListener(topics = "${kafka.topic.name:test-topic}", clientIdPrefix = "neo", groupId = "${kafka.consumer.groupId:test-consumer-group}", concurrency = "4")
public void receive(@Payload String payload, Consumer<String, String> consumer) {
LOGGER.info("Consumer='{}' received payload='{}'", consumer.groupMetadata()
.memberId(), payload);
this.payload = payload;
latch.countDown();
}
ConsumerId
(也称为memberId
)的值遵循特定模式。它以clientIdPrefix
开头,后面跟着基于组内消费者数量的计数器,最后是UUID。
5.2. 使用Kafka CLI
我们也可以通过命令行界面(CLI)配置GroupId
和ConsumerId
。我们将使用kafka-console-consumer.sh
脚本。让我们以group.id
设为test-consumer-group
和client.id
属性设为neo-sequence_number:
的方式启动一个控制台消费者:
$ kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic Test --group test-consumer-group --consumer-property "client.id=neo-1"
在这种情况下,我们必须确保每个客户端具有唯一的client.id
。这与Spring Kafka的行为不同,我们在那里设置了clientIdPrefix
,框架会添加一个序列号到它。如果我们描述消费者组,我们会看到Kafka为每个消费者生成的ConsumerId
:
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-consumer-group --describe
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
test-consumer-group Test 0 0 0 0 neo-1-975feb3f-9e5a-424b-9da3-c2ec3bc475d6 /127.0.0.1 neo-1
test-consumer-group Test 1 0 0 0 neo-1-975feb3f-9e5a-424b-9da3-c2ec3bc475d6 /127.0.0.1 neo-1
test-consumer-group Test 2 0 0 0 neo-1-975feb3f-9e5a-424b-9da3-c2ec3bc475d6 /127.0.0.1 neo-1
test-consumer-group Test 3 0 0 0 neo-1-975feb3f-9e5a-424b-9da3-c2ec3bc475d6 /127.0.0.1 neo-1
test-consumer-group Test 7 0 0 0 neo-3-09b8d4ee-5f03-4386-94b1-e068320b5e6a /127.0.0.1 neo-3
test-consumer-group Test 8 0 0 0 neo-3-09b8d4ee-5f03-4386-94b1-e068320b5e6a /127.0.0.1 neo-3
test-consumer-group Test 9 0 0 0 neo-3-09b8d4ee-5f03-4386-94b1-e068320b5e6a /127.0.0.1 neo-3
test-consumer-group Test 4 0 0 0 neo-2-6a39714e-4bdd-4ab8-bc8c-5463d78032ec /127.0.0.1 neo-2
test-consumer-group Test 5 0 0 0 neo-2-6a39714e-4bdd-4ab8-bc8c-5463d78032ec /127.0.0.1 neo-2
test-consumer-group Test 6 0 0 0 neo-2-6a39714e-4bdd-4ab8-bc8c-5463d78032ec /127.0.0.1 neo-2
6. 总结
以下是讨论的三个标识符的关键区别:
维度 | GroupId |
ConsumerId |
ClientId |
---|---|---|---|
标识什么 | 消费者组 | 消费者组内的单个消费者 | 消费者组内的单个消费者 |
值来自何处 | 开发者设置GroupId |
Kafka根据client.id 消费者属性生成ConsumerId |
开发者设置client.id 消费者属性 |
是否唯一 | 如果两个消费者组有相同的GroupId ,它们实际上是一个 |
Kafka确保每个消费者都有一个唯一值 | 不一定。根据应用场景,两个消费者可以给client.id 消费者属性设置相同的值 |
7. 结论
在这篇文章中,我们探讨了与Kafka消费者相关的几个关键标识符:GroupId
、ClientId
和ConsumerId
。现在我们理解了它们的目的以及如何配置它们。
如往常一样,完整的源代码可以在GitHub上找到。