自托管 NServiceBus ASP.NET 端点而非其他进程的 MSDTC 失败

MSDTC fails for self-hosted NServiceBus ASP.NET endpoints but not other processes

我有一个 Windows 2008 R2 服务器,它托管许多后端 NServiceBus 端点。所有依赖于 NServiceBus.Host.exe 主机(安装为 Windows 服务)的服务都能够与 MSDTC 完美交互,全天平均有少量并发分布式事务。然而,有 2 个小型 Web.API 应用程序自托管 NServiceBus 端点(作为发布者),它们在尝试处理订阅请求时不断收到以下错误:

NServiceBus.Transports.Msmq.MsmqDequeueStrategy Error in receiving messages. System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.Transactions.TransactionManagerCommunicationException: Communication with the underlying transaction manager has failed. ---> System.Runtime.InteropServices.COMException: The Transaction Manager is not available. (Exception from HRESULT: 0x8004D01B) at System.Transactions.Oletx.IDtcProxyShimFactory.ConnectToProxy(String nodeName, Guid resourceManagerIdentifier, IntPtr managedIdentifier, Boolean& nodeNameMatches, UInt32& whereaboutsSize, CoTaskMemHandle& whereaboutsBuffer, IResourceManagerShim& resourceManagerShim) at System.Transactions.Oletx.DtcTransactionManager.Initialize() --- End of inner exception stack trace --- at System.Transactions.Oletx.OletxTransactionManager.ProxyException(COMException comException) at System.Transactions.Oletx.DtcTransactionManager.Initialize() at System.Transactions.Oletx.DtcTransactionManager.get_ProxyShimFactory() at System.Transactions.Oletx.OletxTransactionManager.CreateTransaction(TransactionOptions properties) at System.Transactions.TransactionStatePromoted.EnterState(InternalTransaction tx) --- End of inner exception stack trace --- at System.Transactions.TransactionStateAborted.CheckForFinishedTransaction(InternalTransaction tx) at System.Transactions.Transaction.Promote() at System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction) at System.Transactions.TransactionInterop.GetDtcTransaction(Transaction transaction) at System.Messaging.MessageQueue.StaleSafeReceiveMessage(UInt32 timeout, Int32 action, MQPROPS properties, NativeOverlapped* overlapped, ReceiveCallback receiveCallback, CursorHandle cursorHandle, IntPtr transaction) at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType) at System.Messaging.MessageQueue.Receive(TimeSpan timeout, MessageQueueTransactionType transactionType) at NServiceBus.Transports.Msmq.MsmqDequeueStrategy.ReceiveMessage(Func`1 receive) in c:\BuildAgent\workf8c64a6e8a2d7c\src\NServiceBus.Core\Transports\Msmq\MsmqDequeueStrategy.cs:line 313

一些其他注意事项:

以下对话的补充说明

不是真正的答案,但评论太长了。

您的操作的哪一部分需要 DTC?分布式事务会在需要时自动登记,通常是在您与两个不同的支持 DTC 的基础设施(例如 MSMQ 和数据库)对话时。

您说您通过 DTC 跟踪进行了测试——您是说 DTC Ping 吗?您是否通过在两台机器(或所有机器,如果交易中涉及多于两台机器)上使用 运行 进行测试? DTC 工具非常深奥,其输出可能令人困惑。

另外,如果它在重启前确实有效,是否可以重启重置防火墙设置?防火墙是 DTC 问题的常见原因。

此外,我假设您检查并重新检查了本地机器上的 DTC 设置?您是否确保将 MSMQ 队列设置为事务性队列?

来自您的评论:

Note that this particular failure occurs when attempting to dequeue a message from a local private MSMQ queue [...]

堆栈跟踪显示它正在做的就是这些,但我怀疑它在尝试出队时也在尝试征集多个服务器之间的事务。见下文。

Why MSDTC? It's the original way to support exactly-once messaging in NServiceBus (see here).

是的,但我要问的是为什么特定操作 需要 分布式事务。如果处理程序所做的只是从队列中读取和(例如)将输出写入控制台,则 MSDTC 将永远不会被征用,即使处理程序被包装在事务范围内也是如此。它将简单地使用本地事务从队列中读取。升级到分布式事务是自动的,只有在需要支持多个基础架构时才会发生。

因此,如果您最近在将数据写入新数据库服务器的处理程序中部署了代码,您可能会遇到故障,因为您现在正在征用包含新服务器的事务,这可能是发生故障的地方.

所以确定分布式事务涉及的所有服务器是第一步。下一步是检查所有相关服务器上的 DTC 设置。如果 DTC 设置不是问题,我建议使用 DTCPing 测试服务器之间的通信。 NServiceBus documentation 有一些关于使用 DTCPing 的很好的说明。

"fixed" 这对我们在生产环境中的作用是将应用程序池身份用户添加到服务器上的本地管理员组。不幸的是,我们没有时间确定哪些设置需要安全设置,因为这在其他类似服务器中不是必需的配置。此外,从安全角度来看,这不是最理想的解决方案,但在我们的特定情况下,我们愿意接受它。