9

这是场景:

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 再次。基本上,每条消息都应该轮询订阅每条消息的每个负载平衡服务,并按每个正在连接的服务分组。在不创建多个主题的情况下这可能吗?

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

4

2 回答 2

8

一、话题

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

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

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

来源:MSDN 文章

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

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)
于 2017-03-26T22:29:34.057 回答
1

我想尽最大努力跨多个服务进行负载平衡。这可能吗?

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

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

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

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

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

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

于 2017-03-27T03:46:54.017 回答