Kafka 主题和微服务的多个实例

问题描述

这更像是一个系统设计问题。

假设我有一个微服务架构,我有 X 个实例 Service B(用于对服务的 HTTP 请求进行负载平衡)。但是,Service B 也是一些 Kafka 主题的消费者。如何避免处理同一条消息 X 次(X 是 Service B 的实例数)?如果处理是幂等的,at least once 可能没问题。它不需要是 exactly once,但不能是 X times

服务 A 可以是订单服务。它产生关于用户订单主题下订单的消息。

服务 B 可以是支付服务。它使用来自订单主题的消息来向用户收费。

支付订单可能是幂等操作。但是,如果我有 10 个 Payment Service 实例,我不想浪费 cpu 和 IO 做 10 次。

即使分区是答案,如果我们拥有比分区更多的特定微服务实例怎么办?

解决方法

Kafka 消费者群体

当您有 x 个服务实例并且您希望该服务只使用一次消息时,这是 Kafka 的消费者组概念所关注的事情。 >

本质上,您需要为您的服务实例指定一个通用 kafka 消费者组 ID,然后 kafka 会负责将主题的分区分配给您服务的不同消费者实例,以便没有消息被您的服务消耗两次。

您正在使用的 kafka 消费者库中的 kafka 消费者配置中会有一个消费者组 ID 的配置。您只需要确保为该配置的一组服务实例分配了相同的使用者组 ID 值。

举例说明

如果您的服务 B10 个实例,则为所有 10 个实例指定一个通用 kafka 消费者组 ID,例如 serviceBConsumerGroup。当从具有 10 个分区的 kafka 主题开始消费时,kafka 负责将主题的分区分配给消费者组 serviceBConsumerGroup 的所有实例。所以本质上它会将每个分区分配给每个实例(当有 10 个服务实例和 10 个主题分区时)。如果有 5 个服务实例和 10 个 kafka 主题分区,Kafka 会为每个实例分配 2 个分区用于消费。

阅读有关 Kafka 消费者组的一些参考资料:

,

根据问题,

即使您有多个服务实例,您也无需担心同一消息的重新处理。因为 Kafka 处理消费者偏移量,如果您一旦阅读了消息,我们就会提交该消息的偏移量,以便该消息对该消费者(组)不可用。

举个例子,

订单服务在订单主题和订阅它的支付服务上发布消息。我们有 10 个支付服务实例。在这种情况下,让我们考虑由 Payment 服务实例 1(如果您没有明确定义它属于默认消费者组)消费的消息 1。消费消息 1 后,支付服务实例 1 提交该消息的偏移量(在消费者组级别),它将被视为消息已成功处理。所以支付服务实例 2/任何其他实例只会选择偏移量未提交的消息。

根据@Madhu 的回答,它是为了更快和并行处理消息。如果您有 10 个支付服务实例,并且想要快速访问和处理消息,那么您可以在消费者组下添加更多消费者(但需要考虑订单主题的分区数,因为如果订单主题有 4 个分区,我们定义了 5 个消费者然后1 个消费者始终处于空闲状态,除非任何其他消费者出现故障)。