当Pub/Sub 发生在 NServiceBus 中时,有一个逻辑发布者向多个逻辑订阅者发送事件。每个逻辑订阅者只会收到每个已发布事件的副本。
如果许多订阅者代表同一个逻辑实体,则每个事件将仅由该逻辑实体中的一个订阅者处理。如果两个订阅者共享Endpoint Name,则认为它们代表相同的逻辑实体。
在这种情况下,如果桌面应用程序的每个实例都具有相同的端点名称,则它们被认为代表相同的逻辑实体。发布事件后,只有其中一个桌面应用程序实例会获得该事件的副本。这可能不是你想要的。
如果您为桌面应用程序的每个实例指定不同的端点名称,那么它们各自代表自己的逻辑实体。发布事件后,所有桌面实例都将获得该事件的副本。这也可能不是你想要的。
要考虑的另一件事是 NSB 中的 pub/sub 是持久且可靠的。如果您启动桌面应用程序并设置订阅,则即使桌面应用程序处于脱机状态,该订阅仍然有效。消息可能会排队等待桌面应用程序重新联机以进行处理,即使您从未再次运行桌面应用程序也是如此。您的桌面应用程序需要这些,还是您只关心连接时发生的事件?
如果您想在服务器上发生事件时通知在线的特定订阅者或订阅者子集,那么我会在使用 NSB 之前使用 SignalR。
附加信息
MSMQ 和 SQL Server 不支持开箱即用的 pub-sub,因此它们使用称为消息驱动订阅的功能。消息驱动订阅的工作方式是让订阅者在启动时向发布者发送消息(或调用Subscribe())。此消息包含一个Reply To 标头,发布者存储并使用该标头发送已发布的每条消息的副本。
对于 SQL Server 传输,Reply To 地址将是端点的名称。这又被映射到数据库中表示消息队列的表。如果多个订阅者共享相同的端点名称(因此共享同一个表),那么他们将在它们之间获得一份事件副本,并且将竞争查看哪个订阅者将其从队列中拉出。
对于 MSMQ,Reply To 地址将是端点的名称和机器的名称,由 @ 符号分隔。这意味着每个订阅将针对不同的地址。事件发布后,每个订阅者都将获得它自己的副本。如果多个订阅者代表同一个逻辑实体(即共享一个端点名称),那么您应该有一个distributor in front of them。当您这样做时,传出订阅消息上的Reply To 标头将是分发器的地址。当一个事件被发布时,它总是会被分发给分发者,分发者会将它交给一个(并且只有一个)它的工作人员进行处理。
Rabbit MQ 和 Azure 服务总线具有内置的发布/订阅机制,但它们的行为方式类似于 SQL 传输。逻辑订阅者的一个实例将获得事件的副本。