Azure 服务总线 - 多个服务的循环主题

Azure Service Bus - Round Robin Topic to Multiple Services

场景如下:

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 再次。基本上,每条消息都应该循环到订阅每条消息的每个负载平衡服务,按连接的每个服务分组。这是否可以不创建多个主题?

即使不是循环法,我也想尽最大努力在多个服务之间进行负载平衡。这可能吗?

1。主题

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

A topic subscription resembles a virtual queue that receives copies of the messages that are sent to the topic. Messages are received from a subscription identically to the way they are received from a queue...

Subscriptions support the same patterns described earlier in this section with regard to queues: competing consumer, temporal decoupling, load leveling, and load balancing.

来源: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

一个。创建主题订阅

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

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

乙。收听现有订阅

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)

I'd like to use best effort to load balance across multiple services. Is this possible?

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

The problem I'm trying to solve, is I only want 1 consumer in each service consuming messages on a single topic. Is this possible with ASB?

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

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

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

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