2011-01-20 11 views
8

Estoy escribiendo este post aquí con la esperanza de que alguien me pueda ayudar.NServiceBus MSDTC aflicciones

Estoy tratando de implementar NServiceBus en una aplicación ASP.NET MVC. He revisado todos y cada uno de los pasos para asegurarme de que todo está conectado correctamente. Tengo un evento que le pasa un identificador de trabajo a mi controlador que luego realiza una consulta de Linq a SQL y busca un trabajo y luego envía una alerta por correo electrónico. El proceso es muy simple.

Sin embargo, no puedo por mi vida hacer que MSDTC funcione. Sigo recibiendo el siguiente error:

Así es como he configurado mi autobús:

Bus = NServiceBus.Configure.WithWeb() 
      .Log4Net() 
      .DefaultBuilder() 
      .XmlSerializer() 
      .MsmqTransport() 
       .IsTransactional(false) 
       .PurgeOnStartup(false) 
      .UnicastBus() 
       .ImpersonateSender(false) 
      .CreateBus() 
      .Start(); 

No estoy usando transacciones, así que sé que es un hecho que MSDTC no se debería llamar.

código Mi Handler es el siguiente:

public void Handle(ApplyJobMessage message) 
    { 
     if (message != null) 
     { 
      using(var context = new MyContext()) 
      { 
       JobPosting posting = (from c in context.JobPostings 
       where c.JobPostingId == message.JobId 
       select c).SingleOrDefault(); 
      } 

El punto final se configura de la siguiente manera:

public class MessageEndpoint : IConfigureThisEndpoint, AsA_Server, IWantToRunAtStartup 

Todo funciona muy bien. El mensaje llega correctamente cuando lo haga:

Bus.Send(message); 

Sin embargo, se produce el error MSDTC como se muestra:

2011-01-20 00:55:09,744 [Worker.5] ERROR NServiceBus.Unicast.UnicastBus [(null)] 
<(null)> - JobApplicationHandler Failed handling message. 
System.Runtime.InteropServices.COMException (0x8004D02A): The MSDTC transaction 
manager was unable to push the transaction to the destination transaction manage 
r due to communication problems. Possible causes are: a firewall is present and 
it doesn't have an exception for the MSDTC process, the two machines cannot find 
each other by their NetBIOS names, or the support for network transactions is n 
ot enabled for one of the two transaction managers. (Exception from HRESULT: 0x8 
004D02A) 
    at **System.Transactions.Oletx.ITransactionShim.Export**(UInt32 whereaboutsSize, 
Byte[] whereabouts, Int32& cookieIndex, UInt32& cookieSize, CoTaskMemHandle& coo 
kieBuffer) 
    at System.Transactions.TransactionInterop.GetExportCookie(Transaction transac 
tion, Byte[] whereabouts) 
2011-01-20 00:55:09,749 [Worker.5] WARN NServiceBus.Unicast.Transport.Msmq.Msmq 
Transport [(null)] <(null)> - Failed raising 'transport message received' event 
for message with ID=9cb4b136-e110-4b87-81f6-ee4cd3fcaf46\6151 
System.Reflection.TargetInvocationException: Exception has been thrown by the ta 
rget of an invocation. ---> System.Transactions.TransactionManagerCommunicationE 
xception: Communication with the underlying transaction manager has failed. ---> 
System.Runtime.InteropServices.COMException (0x8004D02A): The MSDTC transaction 
manager was unable to push the transaction to the destination transaction manag 
er due to communication problems. Possible causes are: a firewall is present and 
it doesn't have an exception for the MSDTC process, the two machines cannot fin 
d each other by their NetBIOS names, or the support for network transactions is 
not enabled for one of the two transaction managers. (Exception from HRESULT: 0x 
8004D02A) 
    at System.Transactions.Oletx.ITransactionShim.Export(UInt32 whereaboutsSize, 
Byte[] whereabouts, Int32& cookieIndex, UInt32& cookieSize, CoTaskMemHandle& coo 
kieBuffer) 
    at System.Transactions.TransactionInterop.GetExportCookie(Transaction transac 
tion, Byte[] whereabouts) 
    --- End of inner exception stack trace --- 
    at System.Transactions.TransactionInterop.GetExportCookie(Transaction transac 
tion, Byte[] whereabouts) 
    at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transacti 
on transaction, Byte[] whereAbouts) 
    at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) 
    at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) 
    at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transa 
ction) 
    at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transacti 
on transaction) 
    at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection ownin 
gObject) 
    at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection ow 
ningConnection) 
    at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection ou 
terConnection, DbConnectionFactory connectionFactory) 
    at System.Data.SqlClient.SqlConnection.Open() 
    at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionU 
ser user) 
    at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe() 
    at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode() 
    at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider 
.Execute(Expression query) 
    at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Express 
ion expression) 
    at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source) 

He tratado DTC ping y funciona con éxito, así que sé que es un hecho que ISN MSDTC' el problema He leído que NHibernate tenía problemas similares con NServiceBus pero no he podido establecer ningún paralelismo con LINQ to SQL.

Cualquier ayuda en esta materia sería muy apreciada.

+0

debo añadir que cuando intento esto con la base de datos en mi local de la caja, todo parece funcionar. Ahora tengo mucha curiosidad de por qué no funcionaría con la base de datos en el cuadro remoto. –

+0

¿Cuál es el sistema operativo de la máquina manejadora y de la máquina de base de datos? ¿La máquina de la base de datos permite las transacciones entrantes? ¿Cuál es el mecanismo de autenticación configurado en DTC tanto para la máquina manejadora como para la máquina DB? –

Respuesta

10

Tuve un problema similar y descubrí que la causa era más LINQ-a-SQL que NServiceBus. Si observa su rastro de pila, verá que la causa raíz son sus bibliotecas LINQ y SqlClient, no NSB. La solución que terminé usando, que puede o no funcionar para usted dependiendo de cuán importante es para su acceso a datos ser transaccional, fue desactivar explícitamente las transacciones en mi código LINQ to SQL.En mi caso, yo era simplemente llamar a un procedimiento almacenado utilizando LINQ a SQL, con código como el siguiente:

 public void Save(SomeEvent someEvent) 
     { 
      using (new TransactionScope(TransactionScopeOption.Suppress)) 
      { 
       _loggingDatabaseConnection.DataContext.log_ClickInsert(
someEvent.LogDate, 
someEvent.Id, 
someEvent.OtherStuffGoesHere); 
      } 

La parte importante aquí es la TransactionScope y TransactionScopeOption.Suppress. Esto garantiza que LINQ to SQL no intente incluir la llamada en una transacción utilizando el DTC. Esto está funcionando en mi solución en mi controlador de mensajes (NServiceBus Generic Host).

+0

observación muy interesante. No utilizamos TransactionScope para nuestros escenarios de acceso a datos. Usamos las Transacciones de Linq cuando sea necesario. Por supuesto, realmente no necesitamos ninguna transacción para los artículos que estamos usando en NSB, pero tengo curiosidad por saber cómo podemos utilizarlos si surge alguna situación. Gracias de nuevo por su solución, casi me quité el pelo tratando de configurar MSDTC cuando el problema real mentía dentro de LINQ. Obviamente, no pensé en TransactionScope porque no lo estaba usando. –

1

Recuerdo haber tenido problemas con MSDTC, pero por mi vida no puedo encontrar los blogs/posts/lo que sea que mencioné para resolver el problema. De todos modos, si ese programa ping funciona, es un poco raro. Una sugerencia que puede añadir está tratando de agregar la línea,

.RunCustomAction(() => 
    NServiceBus.Configure.Instance.Configurer.ConfigureProperty<MsmqSubscriptionStorage>(
    msg => msg.DontUseExternalTransaction, true)) 

justo antes de la línea .CreateBus(). Si usa suscripciones, esto le indicará a la suscripción que deje de usar transacciones, lo cual puede ser su problema. Sin embargo, ser advertido al hacer esto hará que sus suscripciones sean menos confiables, así que no lo use en situaciones críticas.

6

Lo que noto es que está configurando NServiceBus como servidor, lo que significa que es transaccional. Creo que lo que tienes aquí es una aplicación web no transaccional que envía mensajes a un servidor transaccional.

+1

Si marca el punto final AsA_Server es equivalente a IsTransactional (verdadero). En realidad anula cualquier IsTransactional (falso) que haya configurado. Quizás @AnupMarwadi, ¿debería marcar su punto final como 'AsA_Client'? –

Cuestiones relacionadas