首页 文章

在微服务的发布/订阅模型中,如何每种服务类型只接收/使用一次消息

提问于
浏览
4

我们正在设计一个微服务架构模型,其中服务A发布消息和服务B,而C希望接收/消费该消息 . 但是,对于高可用性,服务B和C的多个实例同时运行 . 现在的问题是我们如何设计使得只有一个B的服务实例和一个C的服务实例接收消息而不是所有其他服务实例 .

据我所知,RabbitMQ实现这种行为并不容易 . 我想知道Kafka或任何其他消息传递框架是否内置了对此场景的支持,我认为这在微服务架构中应该非常普遍 .

4 回答

  • 1

    Kafka内置了对此方案的支持 .

    您可以创建两个Consumer Groups,一个用于 B ,另一个用于 C . Consumer Groups 订阅来自 A 的消息 .

    A 发布的任何消息都将发送给两个组 . 但是,每个组中只有一个成员可以接收该消息 .

  • 1

    这是您需要执行的更改,以实现与Rabbit MQ相同的更改

    • 创建2个单独的队列,每个B和C服务一个队列

    • 更改逻辑以从队列中读取消息,这样只有一个实例将使用rabbitmq的阻塞连接来从队列中读取消息 .

    这样,当B和C的多个实例都在运行时,两者都将获得消息,并且仍然可以扩展 .

  • 2

    Kafka有一个名为Consumer Groups的功能,它完全符合您的描述 .

    B的每个相同实例都可以将其group.id声明为相同的字符串(比如“serviceB”),Kafka将确保为每个实例分配一个互斥的主题分区集,用于它所订阅的所有主题 .

    由于C的所有实例都将具有不同的group.id(比如“serviceC”),因此它们也将获得与B实例相同的消息,但它们将位于独立的Consumer Group中,因此消息仅发送到N个实例中的1个C,最多为最大实例数,即主题分区的总数 .

    您可以动态和独立地向上或向下扩展或缩小B和C的实例数 . 如果任何实例死亡,其余实例将自动重新 balancer 其分配的主题分区,并接管处理死亡实例的消息 .

    数据永远不必存储多次,因此所有这些服务实例仍然只有一个提交日志或“事实来源” .

  • 1

    您还可以使用命令行工具在kafka中测试此用例 .

    你创建一个 生产环境 者

    bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
    

    然后,您可以创建两个不同的使用者组(cgB,cgC)

    bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning --consumer-property group.id=cgB
    
    bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning --consumer-property group.id=cgC
    

    只要您向主题发送消息,两个组(B,C)都将收到消息,但会保存他们独立处理的消息 .

    这里解释得更好:Kafka quickstart

相关问题