【问题标题】:NServiceBus: Cannot enlist the transaction (failed to send msg to audit queue)NServiceBus:无法登记事务(未能将消息发送到审计队列)
【发布时间】:2015-07-27 14:52:07
【问题描述】:

我有一个端点,它与其他三个工作端点一起作为分发者工作。 接收到的消息的处理端点打开一个事务并尝试将一些 xml 数据导入 sql db。如果在此过程中抛出一些异常,则捕获异常,回滚事务并将 xml 数据写入错误文件夹。 简化,看起来是这样的:

public void Handle(doSomethingCmd message)
        {
            System.Data.SqlClient.BeginTransaction();

            try
            {
                //... some xml data import
                throw new Exception();
               //Commit if succeded
            }
            catch (Exception exception)
            {
                System.Data.IDbTransaction.Rollback();
                //...Write file to error folder
            }
        }

首先,事务回滚后不会发生重试。但是,当再次发送消息时,所有工作人员端点(仅工作人员)都会出现异常(无法登记事务,未能将消息发送到控制队列->请参阅下面的堆栈跟踪)并且 nservicebus 确实重试了消息(这导致情况下,该文件在错误文件夹中出现多次) 看起来分布式事务处于无效状态。我可以只交出异常(重新抛出异常),所以 nservicebus 为我处理回滚,但在这种情况下,文件也会多次写入错误文件夹(由于重试机制)

Failed raising  finished message processing event.|NServiceBus.Unicast.Queuing.FailedToSendMessageException: Failed to send message to address: someEndpoint.distributor.control@SRVPS01 ---> System.Messaging.MessageQueueException: Cannot enlist the transaction.
   at System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
   at System.Messaging.MessageQueue.Send(Object obj, MessageQueueTransactionType transactionType)
   at NServiceBus.Transports.Msmq.MsmqMessageSender.Send(TransportMessage message, Address address) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core\Transports\Msmq\MsmqMessageSender.cs:line 49
   --- End of inner exception stack trace ---
   at NServiceBus.Transports.Msmq.MsmqMessageSender.ThrowFailedToSendException(Address address, Exception ex) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core\Transports\Msmq\MsmqMessageSender.cs:line 88
   at NServiceBus.Transports.Msmq.MsmqMessageSender.Send(TransportMessage message, Address address) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core\Transports\Msmq\MsmqMessageSender.cs:line 75
   at NServiceBus.Distributor.MSMQ.ReadyMessages.ReadyMessageSender.SendReadyMessage(String sessionId, Int32 capacityAvailable, Boolean isStarting) in c:\BuildAgent\work\c3100604bbd3ca20\src\NServiceBus.Distributor.MSMQ\ReadyMessages\ReadyMessageSender.cs:line 62
   at NServiceBus.Distributor.MSMQ.ReadyMessages.ReadyMessageSender.TransportOnFinishedMessageProcessing(Object sender, FinishedMessageProcessingEventArgs e) in c:\BuildAgent\work\c3100604bbd3ca20\src\NServiceBus.Distributor.MSMQ\ReadyMessages\ReadyMessageSender.cs:line 50
   at System.EventHandler1.Invoke(Object sender, TEventArgs e)
   at NServiceBus.Unicast.Transport.TransportReceiver.OnFinishedMessageProcessing(TransportMessage msg) in c:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Core\Unicast\Transport\TransportReceiver.cs:line 435
  • NServicebus 版本:4.6.0.0
  • 排队:MSMQ

【问题讨论】:

  • 我会删除 try catch 并让 NServiceBus 处理其工作单元中的事务。

标签: nservicebus distributed-transactions nservicebus-distributor


【解决方案1】:

worker 通过向分发者发送回消息来结束它的工作单元。此发送将加入现有的分布式事务。您得到的错误是由这个新的事务资源试图加入一个已经失败的事务引起的。某些东西将分布式事务标记为回滚。

这通常是由您的代码引起的。您的数据库操作以某种方式失败,或者您可能超出了处理消息的事务超时限制。 (默认一分钟)

检查您的日志以查看您是否使用超过事务超时限制来处理工作器上的消息。

【讨论】:

  • 我在异常处理中显式回滚事务(参见伪代码)以在 sql db 中保持一致的状态。因为在导入xml数据的过程中,涉及到大量不同表的db写操作。我仍然不想出现错误消息或任何重试,但我想在异常处理中将错误文件写入输出文件夹。所以流程是这样的: 1. 导入xml数据,如果无法导入则抛出ex 2. 捕捉ex(不要把ex冒泡到NB) 3. 在ex处理中回滚db 4. 在ex处理中写入错误文件跨度>
  • 我想我必须将实际导入包装到一个不参与 NServiceBus (TransactionScopeOption.RequiresNew) 的新事务范围中
猜你喜欢
  • 1970-01-01
  • 2012-05-20
  • 2011-08-20
  • 1970-01-01
  • 2013-09-30
  • 2015-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多