NServiceBus 是否可以发布到同一 AppDomain 中的订阅者

本文关键字:AppDomain 是否 NServiceBus | 更新日期: 2023-09-27 18:32:05

我有一个简单的网站。在我的 API 控制器中,我正在捕获一个命令并将其发送到处理程序。这非常有效。在处理程序中,我执行一些处理,然后发布事件。该事件永远不会发布。我什至无法开始描述我为使其工作所做的更改列表,但都无济于事。

关于我能看到的在我的应用程序和任何示例之间唯一不同的是,我的应用程序在同一程序集中具有发布者和订阅者。目前,我认为没有必要使用单独的 NServiceBus 进程,尽管我可能会在某个时候这样做。

处理器

public sealed class PortfoliosHandler : IHandleMessages<CreatePortfolioCommand>, IHandleMessages<PortfolioCreatedEvent>
{
    public void Handle(CreatePortfolioCommand message)
    {
        // Processing logic, this executes just fine
        Bus.Publish(new PortfolioCreatedEvent { Name = portfolio.Name });
    }
    public void Handle(PortfolioCreatedEvent message)
    {
        // This NEVER executes
    }
}

配置

<UnicastBusConfig ForwardReceivedMessagesTo="audit">
    <MessageEndpointMappings>
        <add Assembly="Project.Domain" Namespace="Project.Domain.PM.Commands" Endpoint="messagebus" />
        <add Assembly="Project.Domain" Namespace="Project.Domain.PM.Events" Endpoint="messagebus" />
    </MessageEndpointMappings>
</UnicastBusConfig>

配置代码

NServiceBus.Configure.Transactions.Enable();
var config = NServiceBus.Configure.With();
config = config
    .AutofacBuilder(container)
    .Log4Net(new DebugAppender {Threshold = Level.Warn})
    .UseTransport<Msmq>()
    .PurgeOnStartup(true)
    .UnicastBus()
    .LoadMessageHandlers()
    .RunHandlersUnderIncomingPrincipal(false)
    .InMemorySubscriptionStorage()
    .UseInMemoryTimeoutPersister();
var bus = config
    .CreateBus()
    .Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>()
                            .Install());
事件

处理程序不仅永远不会触发,而且队列中也不会出现任何事件消息,日志中也不会显示该消息的发布记录。就好像我从来没有发送过一样。下面是通过调用上述 Publish 方法发出的日志条目:

NServiceBus.Unicast.UnicastBus: 15:52:11,984 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Transports.Msmq.CorrelationIdMutatorForBackwardsCompatibilityWithV3
NServiceBus.Unicast.UnicastBus: 15:52:11,984 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Transports.Msmq.CorrelationIdMutatorForBackwardsCompatibilityWithV3
NServiceBus.Unicast.UnicastBus: 15:52:12,240 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Impersonation.Windows.WindowsIdentityEnricher
NServiceBus.Unicast.UnicastBus: 15:52:12,240 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Impersonation.Windows.WindowsIdentityEnricher
NServiceBus.Unicast.UnicastBus: 15:52:12,488 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Unicast.Monitoring.VersionMutator
NServiceBus.Unicast.UnicastBus: 15:52:12,488 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Unicast.Monitoring.VersionMutator
NServiceBus.Unicast.UnicastBus: 15:52:12,743 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Unicast.Monitoring.SentTimeMutator
NServiceBus.Unicast.UnicastBus: 15:52:12,743 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Unicast.Monitoring.SentTimeMutator
NServiceBus.Unicast.UnicastBus: 15:52:12,984 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Unicast.Monitoring.CausationMutator
NServiceBus.Unicast.UnicastBus: 15:52:12,984 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Unicast.Monitoring.CausationMutator
NServiceBus.Unicast.UnicastBus: 15:52:13,228 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Sagas.OriginatingSagaHeaderMutator
NServiceBus.Unicast.UnicastBus: 15:52:13,228 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Sagas.OriginatingSagaHeaderMutator
NServiceBus.Unicast.UnicastBus: 15:52:13,475 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Sagas.AutoCorrelateSagaOnReplyMutator
NServiceBus.Unicast.UnicastBus: 15:52:13,475 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Sagas.AutoCorrelateSagaOnReplyMutator
NServiceBus.Unicast.UnicastBus: 15:52:13,721 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.MessageHeaders.MessageHeaderManager
NServiceBus.Unicast.UnicastBus: 15:52:13,721 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.MessageHeaders.MessageHeaderManager
NServiceBus.Unicast.UnicastBus: 15:52:13,969 DEBUG UnicastBus:0 - Invoking transport message mutator: NServiceBus.Gateway.HeaderManagement.GatewayHeaderManager
NServiceBus.Unicast.UnicastBus: 15:52:13,969 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Invoking transport message mutator: NServiceBus.Gateway.HeaderManagement.GatewayHeaderManager

以下是此后不久发生的日志条目:

NServiceBus.Unicast.UnicastBus: 15:52:58,866 DEBUG UnicastBus:0 - Finished handling message.
NServiceBus.Unicast.UnicastBus: 15:52:58,866 [23] DEBUG NServiceBus.Unicast.UnicastBus [(null)] <(null)> - Finished handling message.
NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver: 15:53:00,900 DEBUG TimeoutPersisterReceiver:0 - Polling for timeouts at 09/20/2013 15:53:00.
NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver: 15:53:00,900 [17] DEBUG NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver [(null)] <(null)> - Polling for timeouts at 09/20/2013 15:53:00.
NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver: 15:53:01,152 DEBUG TimeoutPersisterReceiver:0 - Polling next retrieval is at 09/20/2013 15:54:01.
NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver: 15:53:01,152 [17] DEBUG NServiceBus.Timeout.Hosting.Windows.TimeoutPersisterReceiver [(null)] <(null)> - Polling next retrieval is at 09/20/2013 15:54:01.

请帮忙。我已尽头。我从MassTransit移植到NServiceBus,特别是因为命令,事件和消息之间的分离,但是经过4天的头撞,MassTransit看起来非常好。

敢肯定我正在做的事情真的很愚蠢,但我是 NServicebus 的菜鸟。我甚至买了这本书来帮助我,但无济于事。我看不出我做错了什么,而且我已经尝试了很多设置排列,我无法全部跟踪它们。

更新 2013/09/23

建议我有:

  • 将处理程序一分为二:PortfolioCreatedHandler 和 CreatePortfolioHandler。
  • 从分拣机上拆下密封
  • 创建了我自己的 SubscriptionStorage,包装 InMemorySubscriptionStorage 用于调试目的

我已经在使用IEvent来标记我的事件,并使用ICommand来标记我的命令。命令由 Web 控制器发布,只有处理程序发布事件。

我的 TestSubscriptionStorage 类是为 Init 和 GetSubscriberAddressesForMessage 调用的,而不是为 Subscribe 和 Ubsubscribe调用的,所以看起来问题是事件没有被订阅,这很难与下面的日志条目协调。

以下是提及 PortfolioCreatedEvent 的日志:

NServiceBus.Unicast.Routing.StaticMessageRouter: 09:34:25,886 DEBUG StaticMessageRouter:0 - Routing for message: Project.Domain.PM.Events.PortfolioCreatedEvent set to messagebus@SL-T50009909L
NServiceBus.Unicast.Routing.StaticMessageRouter: 09:34:25,886 [1] DEBUG NServiceBus.Unicast.Routing.StaticMessageRouter [(null)] <(null)> - Routing for message: Project.Domain.PM.Events.PortfolioCreatedEvent set to messagebus@SL-T50009909L
MessageType: Project.Domain.PM.Events.PortfolioCreatedEvent, Recoverable: True, TimeToBeReceived: Not set
MessageType: Project.Domain.PM.Events.PortfolioCreatedEvent, Recoverable: True, TimeToBeReceived: Not set
NServiceBus.Unicast.MessageHandlerRegistry: 09:34:25,906 DEBUG MessageHandlerRegistry:0 - Associated 'Project.Domain.PM.Events.PortfolioCreatedEvent' message with 'Project.PM.Handers.PortfolioCreatedHandler' handler
NServiceBus.Unicast.MessageHandlerRegistry: 09:34:25,906 [1] DEBUG NServiceBus.Unicast.MessageHandlerRegistry [(null)] <(null)> - Associated 'Project.Domain.PM.Events.PortfolioCreatedEvent' message with 'Project.PM.Handers.PortfolioCreatedHandler' handler
NServiceBus.Unicast.MessageHandlerRegistry: 09:34:25,916 DEBUG MessageHandlerRegistry:0 - Associated 'Project.Domain.PM.Commands.CreatePortfolioCommand' message with 'Project.PM.Handers.CreatePortfolioHandler' handler
NServiceBus.Unicast.MessageHandlerRegistry: 09:34:25,916 [1] DEBUG NServiceBus.Unicast.MessageHandlerRegistry [(null)] <(null)> - Associated 'Project.Domain.PM.Commands.CreatePortfolioCommand' message with 'Project.PM.Handers.CreatePortfolioHandler' handler
NServiceBus.Serializers.XML.XmlMessageSerializer: 09:34:26,120 DEBUG XmlMessageSerializer:0 - Initializing type: Project.Domain.PM.Events.PortfolioCreatedEvent, Project.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
NServiceBus.Serializers.XML.XmlMessageSerializer: 09:34:26,120 [1] DEBUG NServiceBus.Serializers.XML.XmlMessageSerializer [(null)] <(null)> - Initializing type: Project.Domain.PM.Events.PortfolioCreatedEvent, Project.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions.MessageDrivenSubscriptionManager: 09:34:35,445 INFO  MessageDrivenSubscriptionManager:0 - Subscribing to Project.Domain.PM.Events.PortfolioCreatedEvent, Project.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null at publisher queue messagebus@SL-T50009909L
NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions.MessageDrivenSubscriptionManager: 09:34:35,445 [18] INFO  NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions.MessageDrivenSubscriptionManager [(null)] <(null)> - Subscribing to Project.Domain.PM.Events.PortfolioCreatedEvent, Project.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null at publisher queue messagebus@SL-T50009909L
NServiceBus.AutomaticSubscriptions.DefaultAutoSubscriptionStrategy: 09:34:35,555 DEBUG DefaultAutoSubscriptionStrategy:0 - Autosubscribed to event Project.Domain.PM.Events.PortfolioCreatedEvent
NServiceBus.AutomaticSubscriptions.DefaultAutoSubscriptionStrategy: 09:34:35,555 [18] DEBUG NServiceBus.AutomaticSubscriptions.DefaultAutoSubscriptionStrategy [(null)] <(null)> - Autosubscribed to event Project.Domain.PM.Events.PortfolioCreatedEvent

NServiceBus 是否可以发布到同一 AppDomain 中的订阅者

好吧,谢谢你买这本书!是的,您绝对可以订阅来自同一应用程序域的事件。以下是关于可能发生的事情的一些想法。

  • 您是否看到指示他们正在订阅事件的日志条目?如果没有,那么他们就不订阅。
  • 没有为命令和事件发布代码,所以我不确定您使用的是不显眼模式还是直接实现IEvent。NServiceBus 4 不会自动订阅任何未识别为事件的内容。
  • 我在你的代码中看到InMemorySubscriptionStorage。这使得实际查看该存储有点困难。您可以尝试在某处注入ISubscriptionStorage,以便查看调试器中的内容。或者只是切换到默认的 Raven 订阅存储一段时间,以便您可以在 http://localhost:8080 导航到 RavenDB Studio 并查看订阅文档。
  • 我不确定你为什么要密封你的处理程序类。我想不出可能导致的特定问题,但将其取出以消除它作为一个可能的问题可能是个好主意。
  • 尝试将处理程序分离到单独的类中。无论如何,一个类都没有理由同时实现这两个 - 容器将为每条消息启动新实例,因此您无法共享状态,因此最好不要给其他开发人员留下他们可以的印象。
  • 这个问题也可能与此有关?

当然,我有时会因此而成为破纪录,但我会提醒您首先不要从 Web 应用程序发布事件。