【问题标题】:Azure Service Bus - Round Robin Topic to Multiple ServicesAzure 服务总线 - 多个服务的循环主题
【发布时间】:2017-03-26 00:33:11
【问题描述】:

这是场景:

Publisher #1 ═══╗             ╔═══ Round Robin ═══╦═══ Subscriber #1 (Service 1)
                ║             ║                   ╚═══ Subscriber #2 (Service 1)
                ╠═══ Topic ═══╣
                ║             ║                   ╔═══ Subscriber #3 (Service 2)
Publisher #2 ═══╝             ╚═══ Round Robin ═══╩═══ Subscriber #4 (Service 2)

我有一条消息需要由多个订阅者处理,但每个服务只有一个(每个服务将运行多个实例)。

消息#1,需要由订阅者#1 和#3 处理。消息#2,需要由订阅者#2 和#4 处理。消息 #3,订阅者 #1 和 #3 再次。基本上,每条消息都应该轮询订阅每条消息的每个负载平衡服务,并按每个正在连接的服务分组。在不创建多个主题的情况下是否可以这样做?

即使不是轮询,我也想尽最大努力跨多个服务进行负载平衡。这可能吗?

【问题讨论】:

  • 您要解决的问题是什么? ASB 客户作为竞争消费者运营。
  • @SeanFeldman 我要解决的问题是,我只希望每个服务中的 1 个消费者在单个主题上消费消息。 ASB 可以做到这一点吗?

标签: c# azure azureservicebus azure-servicebus-topics


【解决方案1】:

1。主题

主题是一种发布/分发机制,每个订阅(订阅者)将发送一次消息。

主题订阅类似于接收发送到主题的消息副本的虚拟队列。从订阅接收消息的方式与从队列接收消息的方式相同...

订阅支持本节前面关于队列的相同模式:竞争消费者、时间解耦、负载均衡和负载平衡。

来源:MSDN Article

您需要在竞争消费者(服务实例)之间重复使用主题订阅来实现您的场景。

Publisher #1 ═══╗             ╔═══ Subscription 1 ═══╦═══ Service 1-instance 1
                ║             ║                      ╚═══ Service 1-instance 2
                ╠═══ Topic ═══╣
                ║             ║                      ╔═══ Service 2-instance 1
Publisher #2 ═══╝             ╚═══ Subscription 2 ═══╩═══ Service 2-instance 2

A.创建主题订阅

string connectionString = "<Secret>"
var namespaceManager =
    NamespaceManager.CreateFromConnectionString(connectionString);

if (!namespaceManager.SubscriptionExists("TestTopic", "Inventory"))
{
    namespaceManager.CreateSubscription("TestTopic", "Inventory");
}

B.收听现有订阅

MessagingFactory factory = MessagingFactory.Create(uri, tokenProvider);

MessageReceiver receiver = factory.CreateMessageReceiver("TestTopic/subscriptions/Inventory");

2。队列

使用多个Queues 也可以适合您的特定场景。每个具有多个竞争消费者(实例)的Queue 只会将消息传递给第一个请求并成功处理它的客户端。

然后设计变成:

Publisher #1 ═══╗         ╔═══ Service 1 Queue ═══╦═══ Subscriber #1 (Service 1)
                ║         ║                       ╚═══ Subscriber #2 (Service 1)
                ╠═══ASB═══╣
                ║         ║                       ╔═══ Subscriber #3 (Service 2)
Publisher #2 ═══╝         ╚═══ Service 2 Queue ═══╩═══ Subscriber #4 (Service 2)

【讨论】:

  • 我正在尝试将我的单体应用迁移到一堆微服务中。我想避免的是需要处理消息的多个队列,因为现在如果我添加更多需要监听发布者消息的微服务,我需要创建另一个队列并将消息发送到。这似乎不是最好的方法。我有一个消息服务,它正在从 irc 发布消息。我有垃圾邮件服务(禁止垃圾邮件机器人)、琐事服务(检查答案是否正在运行)、命令服务(回复!消息)等等。这是你会采取的方法吗?
  • 现在,我正在尝试在 Service Fabric 上实现此功能,但我正在尝试以一种无需调用我想要传递此消息的每个服务的方式来执行此操作到。我希望订阅者会说“嘿,我想查看消息并处理它们”。如果您可以帮助我解决问题,我很乐意为这个问题添加赏金,并为您提供一些额外的帮助。
  • 我已编辑答案以包含基于主题的解决方案。
  • 队列不处理消息,这些队列的消费者处理。如果你想拥有微服务,我希望看到那些不共享的资源。将队列视为“邮箱”。如果您有一栋带公寓的建筑,则每间公寓都有一个收件箱。他们不共享一个收件箱。您可能正在寻找的是您选择的消息服务之上的抽象。
  • 如何在多台机器上重复使用订阅? (实例)?
【解决方案2】:

我想尽最大努力在多个服务之间实现负载平衡。这可能吗?

根据您的描述,您似乎正在尝试在任何给定服务的多个实例之间进行负载平衡,而不是单个服务。您可以通过 ASB 支持的竞争性消费者模式开箱即用。并不是你真正需要为之工作的。

我要解决的问题是,我只希望每个服务中的 1 个消费者在单个主题上消费消息。 ASB 可以做到这一点吗?

是的,这是可能的。如果您有一个按服务(而非实例)订阅的共享主题,并且包含始终评估为真的规则,SqlFilter (1 = 1)。然后每个订阅者都会得到该消息的副本。本质上,您会将消息广播到您的所有服务。由于竞争消费者,每个服务只有一个实例会收到该消息。

要针对特定​​服务,您需要创建一个额外的规则来过滤掉有关属性(标准属性或自定义属性)的消息。例如,它可以是服务名称。

如果您不想专注于微服务的中间件,您可以看看为您做这件事的框架。这样的框架通常也倾向于提供额外的特性。例如,看看NServiceBus 或 MassTransit。

完全免责声明 - 我正在研究 NServiceBus 及其 ASB 传输。

【讨论】:

  • 我在任何时候都不需要针对特定​​的实例。这个想法是,每个服务都是多余的,所以只要一个实例正在获取消息,我就很高兴。您在回答的后半部分提到“如果您有一个共享主题,每个服务订阅(不是实例)”......我将如何做到这一点?如果每个服务都订阅一次,那不是意味着只有一个实例会收到消息吗?
  • 这是一个非常明显的排队UC,肖恩。绝对没有必要在上面放置任何进一步的抽象
  • 服务在这一点上是一个逻辑概念,因为订阅是由实例使用的。假设您有一个运行 2 个实例的服务 X。每个实例都将创建一个订阅客户端来侦听为服务 X 指定的消息。两个实例将竞争该订阅上的消息。在您最初的问题中,图表上的“循环”订阅实体。
猜你喜欢
  • 2017-06-05
  • 1970-01-01
  • 2019-07-25
  • 2015-11-03
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多