2011-01-20 36 views
8

Tôi đang viết bài đăng này ở đây với hy vọng rằng ai đó có thể giúp tôi.NServiceBus MSDTC tai họa

Tôi đang cố triển khai NServiceBus trên ứng dụng ASP.NET MVC. Tôi đã trải qua từng bước để đảm bảo rằng mọi thứ đều có dây. Tôi có một sự kiện mà chuyển một Id công việc để xử lý của tôi mà sau đó thực hiện một truy vấn LINQ-to-Sql và tìm một công việc và sau đó gửi email một cảnh báo. Quá trình này rất đơn giản.

Tuy nhiên, tôi không thể sống được MSDTC để làm việc. Tôi tiếp tục nhận được lỗi sau:

Dưới đây là cách tôi đã Bus của tôi cấu hình:

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

Tôi không sử dụng giao dịch vì vậy tôi biết một thực tế rằng MSDTC nên thậm chí không được gọi.

My Handler mã như sau:

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(); 
      } 

Các thiết bị đầu cuối được cấu hình như sau:

public class MessageEndpoint : IConfigureThisEndpoint, AsA_Server, IWantToRunAtStartup 

Tất cả mọi thứ hoạt động tốt. Thông điệp đến một cách chính xác khi tôi làm:

Bus.Send(message); 

Tuy nhiên, lỗi MSDTC xảy ra như:

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) 

Tôi đã thử DTC ping và nó hoạt động thành công vì vậy tôi biết một thực tế rằng isn MSDTC' t vấn đề. Tôi đã đọc rằng NHibernate có vấn đề tương tự với NServiceBus nhưng tôi đã không thể rút ra bất kỳ song song trên cùng với LINQ to SQL.

Bất kỳ trợ giúp nào về vấn đề này sẽ rất được đánh giá cao.

+0

Tôi nên thêm điều đó khi tôi thử điều này với cơ sở dữ liệu trên hộp địa phương của tôi, mọi thứ dường như hoạt động. Bây giờ tôi rất tò mò là tại sao nó sẽ không làm việc với cơ sở dữ liệu trên hộp điều khiển từ xa. –

+0

Hệ điều hành của cả máy xử lý và máy cơ sở dữ liệu là gì? Máy cơ sở dữ liệu có cho phép các giao dịch trong nước không? Cơ chế xác thực được thiết lập trong DTC cho cả máy xử lý và máy DB là gì? –

Trả lời

10

Tôi gặp sự cố tương tự và thấy rằng nguyên nhân là LINQ-to-SQL nhiều hơn NServiceBus. Nếu bạn nhìn vào dấu vết ngăn xếp của bạn, bạn sẽ thấy nguyên nhân gốc là thư viện LINQ và SqlClient của bạn, không phải NSB. Các giải pháp mà tôi đã kết thúc bằng cách sử dụng, có thể hoặc có thể không làm việc cho bạn tùy thuộc vào mức độ quan trọng của việc truy cập dữ liệu của bạn là giao dịch, là tắt một cách rõ ràng các giao dịch trong mã LINQ to SQL của tôi.Trong trường hợp của tôi, tôi đã được chỉ đơn giản là gọi một thủ tục lưu trữ sử dụng LINQ to SQL, với mã như thế này:

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

Phần quan trọng ở đây là TransactionScope và TransactionScopeOption.Suppress. Điều này đảm bảo LINQ to SQL không cố gắng tranh thủ cuộc gọi vào một giao dịch bằng DTC. Điều này làm việc trong giải pháp của tôi trong trình xử lý tin nhắn của tôi (NServiceBus Generic Host).

+0

Quan sát rất thú vị. Chúng tôi không sử dụng TransactionScope cho các trường hợp Truy cập Dữ liệu của chúng tôi. Chúng tôi sử dụng Giao dịch LINQ và khi cần thiết. Tất nhiên, chúng tôi không thực sự cần bất kỳ giao dịch nào cho các mục chúng tôi đang sử dụng trên NSB, nhưng tôi tò mò muốn biết cách chúng tôi có thể sử dụng chúng nếu tình huống phát sinh? Cảm ơn bạn một lần nữa cho giải pháp của bạn, tôi gần như kéo tóc của tôi ra cố gắng để cấu hình MSDTC khi vấn đề thực sự nói dối trong LINQ. Rõ ràng, tôi không nghĩ về TransactionScope vì không sử dụng nó. –

1

Tôi có thể nhớ có vấn đề với MSDTC, nhưng trong cuộc sống của tôi không thể tìm thấy các blog/bài viết/bất cứ điều gì tôi tham chiếu để giải quyết vấn đề. Dù sao, nếu chương trình ping đó hoạt động thì nó hơi lạ một chút. Một gợi ý tôi có thể thêm đang cố gắng thêm dòng,

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

ngay trước dòng .CreateBus(). Nếu bạn đang sử dụng đăng ký, điều này sẽ cho đăng ký ngừng sử dụng giao dịch, điều này có thể là vấn đề của bạn. Tuy nhiên, hãy cảnh báo việc này sẽ làm cho đăng ký của bạn kém đáng tin cậy hơn, vì vậy đừng sử dụng nó trong các tình huống quan trọng.

6

Điều tôi nhận thấy là bạn đang định cấu hình NServiceBus làm máy chủ, điều đó có nghĩa là nó giao dịch. Tôi nghĩ rằng những gì bạn có ở đây là một ứng dụng web không giao dịch đang gửi tin nhắn đến một máy chủ giao dịch.

+1

Nếu bạn đánh dấu điểm cuối AsA_Server, nó tương đương với IsTransactional (đúng). Nó thực sự ghi đè bất kỳ IsTransactional (sai) nào mà bạn đã thiết lập. Có lẽ @AnupMarwadi, bạn nên đánh dấu điểm cuối của mình là 'AsA_Client'? –

11

Giải pháp được chấp nhận thực sự là giải pháp cho sự cố. Tôi sẽ đề nghị bạn sử dụng công cụ DTCPing để thiết lập MSDTC đúng cách và tìm ra các vấn đề cơ bản.

Kiểm tra bài viết này để biết thêm thông tin:

MSDTC là khá mơ hồ, chúc may mắn!