【发布时间】:2010-10-15 13:50:42
【问题描述】:
使用的 NServiceBus 版本:2.0.0.1145
问题:
是否可以配置 NServiceBus 主机,使其消费(订阅)他自己发布的消息?
答案:
这似乎是可能的,但在以下配置中,它在尝试将订阅插入订阅存储时给了我一个事务死锁异常。 当您使用 DbSubscriptionStorage 和超过 1 个“NumberOfWorkerThreads”时会发生这种情况。
错误:
Could not execute command:
INSERT INTO Subscription (SubscriberEndpoint, MessageType) VALUES (@p0, @p1)
System.Data.SqlClinet.SqlException:
Transaction was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
之后,NServiceBus 尝试断开连接但失败,因为事务仍在进行中并引发 UnhandledException。
如何重现:
这是我的 App.Config:
<!-- Publishing Configuration -->
<MsmqTransportConfig InputQueue="test_publisher_output" ErrorQueue="test_error" NumberOfWorkerThreads="3" MaxRetries="5" />
<!-- Subscription Configuration -->
<UnicastBusConfig DistributorControlAddress="" DistributorDataAddress="" ForwardReceivedMessagesTo="">
<MessageEndpointMappings>
<add Messages="MessageAssembly" Endpoint="test_publisher_output" />
</MessageEndpointMappings>
</UnicastBusConfig>
我的总线配置:
var bus = Configure.With()
.Log4Net()
.StructureMapBuilder(container)
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.DBSubcriptionStorage(subscriptionDbProperties, true)
.Sagas()
.NHibernateSagaPersister(sagaDbProperties, true)
.UnicastBus()
.ImpersonateSender(false)
.LoadMessageHandlers(First<GridInterceptingMessageHandler>
.Then<SagaMessageHandler>())
.CreateBus()
.Start();
这是我的订阅和传奇数据库的 dbProperties:
connection.provider NHibernate.Connection.DriverConnectionProvider
connection.driver_class NHibernate.Driver.SqlClientDriver
dialect NHibernate.Dialect.MsSql2005Dialect
只要我不将 NumberOfWorkerThreads 增加到 1 以上,一切正常。高于 1 的所有内容都会引发上述错误。
我希望我没有忘记任何事情。提前感谢您的帮助。
【问题讨论】:
-
为什么同一个端点想要订阅它自己发布的消息?我的意思是,如果您想在同一个端点中发生其他事情,您可以将它们放在最初进行发布的代码中。
-
嗨,Udi,因为我会放松 nservicebus 给我的稳定性。我想将一大堆工作分解成由消息处理程序执行的小包。这里完成的工作示例是调用 web 服务、打开 ftp 连接、创建和转换 xml 文件、数据库事务等。我也希望可以选择仅发布或发送消息,并且不想关心端点。应用程序的管理员应该决定在哪里托管端点。在最简单的配置中,这一系列工作应该在一个主机中完成。
标签: nservicebus publish-subscribe database-deadlocks