Случайное исключение MSDTC с WCF над MSMQ - PullRequest
2 голосов
/ 22 июля 2011

У нас есть служба, которая выполняет вызовы WCF через MSMQ, используя NetMsmqBinding. К сожалению, мы видим случайное (каждые несколько дней после тысячи вызовов) AccessViolationException, выходящее из службы MSDTC. Эта ошибка возникает только на физически старых производственных системах XP, и я не могу воссоздать ее в dev. Я даже прибегал к созданию образов и запуску реальных производственных экземпляров на виртуальных машинах, но все работает хорошо в течение нескольких дней. Я сравнил номера версий каждого dll MSMQ и связанных с MSDTC, которые я могу найти, и все они совпадают. Обновления Windows были применены недавно. Конечные точки WCF работают с одним InstanceContextMode, а для параметра ConcurrencyMode также установлено значение single.

Если не считать фактического решения проблемы, могу ли я в любом случае перехватить / восстановить следующую ошибку?

Есть ли способ удержать NetMsmqBinding от продвижения транзакции? Мы не используем никаких других ресурсов, кроме самих очередей.

The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
   at System.Transactions.Oletx.IDtcProxyShimFactory.BeginTransaction(UInt32, System.Transactions.Oletx.OletxTransactionIsolationLevel, IntPtr, System.Guid ByRef, System.Transactions.Oletx.ITransactionShim ByRef)
   at System.Transactions.Oletx.OletxTransactionManager.CreateTransaction(System.Transactions.TransactionOptions)
   at System.Transactions.TransactionStatePromoted.EnterState(System.Transactions.InternalTransaction)
   at System.Transactions.EnlistableStates.Promote(System.Transactions.InternalTransaction)
   at System.Transactions.Transaction.Promote()
   at System.Transactions.TransactionInterop.ConvertToOletxTransaction(System.Transactions.Transaction)
   at System.Transactions.TransactionInterop.GetDtcTransaction(System.Transactions.Transaction)
   at System.ServiceModel.Channels.MsmqQueue.GetNativeTransaction(System.ServiceModel.Channels.MsmqTransactionMode)
   at System.ServiceModel.Channels.MsmqQueue.ReceiveCoreDtcTransacted(System.ServiceModel.Channels.MsmqQueueHandle, System.ServiceModel.Channels.NativeMsmqMessage, System.TimeSpan, System.ServiceModel.Channels.MsmqTransactionMode, Int32)
   at System.ServiceModel.Channels.MsmqQueue.ReceiveCore(System.ServiceModel.Channels.MsmqQueueHandle, System.ServiceModel.Channels.NativeMsmqMessage, System.TimeSpan, System.ServiceModel.Channels.MsmqTransactionMode, Int32)
   at System.ServiceModel.Channels.MsmqQueue.TryReceiveInternal(System.ServiceModel.Channels.NativeMsmqMessage, System.TimeSpan, System.ServiceModel.Channels.MsmqTransactionMode, Int32)
   at System.ServiceModel.Channels.MsmqQueue.TryReceive(System.ServiceModel.Channels.NativeMsmqMessage, System.TimeSpan, System.ServiceModel.Channels.MsmqTransactionMode)
   at System.ServiceModel.Channels.MsmqReceiveHelper.TryReceive(System.ServiceModel.Channels.MsmqInputMessage, System.TimeSpan, System.ServiceModel.Channels.MsmqTransactionMode, System.ServiceModel.Channels.MsmqMessageProperty ByRef)
   at System.ServiceModel.Channels.MsmqInputChannelBase.TryReceive(System.TimeSpan, System.ServiceModel.Channels.Message ByRef)
   at System.ServiceModel.Channels.SecurityChannelListener`1+SecurityInputChannel[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].TryReceive(System.TimeSpan, System.ServiceModel.Channels.Message ByRef)
   at System.ServiceModel.Dispatcher.InputChannelBinder.TryReceive(System.TimeSpan, System.ServiceModel.Channels.RequestContext ByRef)
   at System.ServiceModel.Dispatcher.ErrorHandlingReceiver.TryReceive(System.TimeSpan, System.ServiceModel.Channels.RequestContext ByRef)
   at System.ServiceModel.Dispatcher.ChannelHandler.TryTransactionalReceive(System.Transactions.Transaction, System.ServiceModel.Channels.RequestContext ByRef)
   at System.ServiceModel.Dispatcher.ChannelHandler.TransactedLoop()
   at System.ServiceModel.Dispatcher.ChannelHandler.SyncTransactionalMessagePump()
   at System.ServiceModel.Dispatcher.ChannelHandler.OnStartSyncMessagePump(System.Object)
   at System.Runtime.IOThreadScheduler+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
   at System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

1 Ответ

2 голосов
/ 22 июля 2011

Ваша служба настроена для работы в качестве одноэлементного экземпляра. У вас могут быть проблемы с многопоточностью при DTC, когда служба вызывается под нагрузкой несколькими клиентами. Если вы абсолютно не уверены, что вам нужно запускать службу как одиночную, а код службы является поточно-ориентированным, вам следует использовать InstanceContextMode для каждого вызова или для каждого сеанса (в зависимости от конфигурации безопасности).

Вы также можете попытаться пометить реализацию метода операции сервиса с помощью:

[OperationBehavior(TransactionScopeRequired = false)]

, а также предотвращает включение кода внутри метода в окружающую транзакцию, создаваемую MSMQ для обработки вашего сообщения.

...