2012-02-23 36 views
5

Tôi có một tình huống sau đây:NServiceBus - Cách nhận hàng đợi riêng cho mỗi người nhận loại tin nhắn đăng ký?

enter image description here

Vì vậy, nhận đặt mua hai loại sự kiện: eventA và eventB. NServiceBus tạo hàng đợi cho người nhận (người nhận) và các thông điệp địa điểm của loại eventA và eventB đến cùng một hàng đợi. Câu hỏi là, nếu tôi có thể cấu hình NServiceBus để sử dụng hàng đợi riêng biệt (ReceiveEventA và ReceiverEventB) cho mỗi loại sự kiện cho người nhận? Hoặc tôi có thể có hai người nhận trong một quá trình (và mỗi người nhận hàng đợi riêng biệt). Điều là EventA mất nhiều thời gian để xử lý hơn EventB và chúng độc lập - vì vậy nếu chúng nằm trong hàng đợi riêng biệt, chúng có thể được xử lý đồng thời.

Cập nhật: Nếu tôi đi với cách tiếp cận ngây thơ như thế này, nhận thất bại trong việc bắt đầu với tài liệu tham khảo ngoại lệ null:

private static IBus GetBus<THandler, TEvent>() 
    {     
     var bus = Configure.With(new List<Type> 
            { 
             typeof(THandler), 
             typeof(TEvent), 
             typeof(CompletionMessage) 
            }) 
      .Log4Net() 
      .DefaultBuilder() 
      .XmlSerializer() 
      .MsmqTransport() 
      .IsTransactional(true) 
      .PurgeOnStartup(false) 
      .UnicastBus() 
      .LoadMessageHandlers() 
      .ImpersonateSender(false); 

     bus.Configurer.ConfigureProperty<MsmqTransport>(x => x.InputQueue, "Queue" + typeof(THandler).Name); 

     return bus.CreateBus().Start(); 
    } 

    [STAThread] 
    static void Main() 
    { 
     Busses = new List<IBus> 
        { 
         GetBus<ItemEventHandlerA, ItemEventA>(), 
         GetBus<ItemEventHandlerB, ItemEventB>() 
        };   

     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new TestForm()); 
    } 

ngoại lệ stack trace là:

tại NServiceBusTest2.WinFormsReceiver.Program .GetBusTHandler, TEvent trong C: \ Users \ User \ Documents \ Visual Studio 2010 \ Projects \ NServiceBusTest2 \ NServiceBusTest2.WinFormsReceiver \ Program.cs: dòng 57
tại NServiceBusTest2.WinFormsReceiver.Program.Main() trong C: \ Users \ Người dùng \ Documents \ Visual Studio 2 010 \ Projects \ NServiceBusTest2 \ NServiceBusTest2.WinFormsReceiver \ Program.cs: dòng 26
tại System.AppDomain._nExecuteAssembly (lắp ráp RuntimeAssembly, String [] args)
tại System.AppDomain.ExecuteAssembly (String assemblyFile, Bằng chứng assemblySecurity, String [ ] args) tại Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
tại System.Threading.ThreadHelper.ThreadStart_Context (bang Object)
tại System.Threading.ExecutionContext.Run (executionContext executionContext, ContextCallback gọi lại, đối tượng nhà nước, Boolean ignoreSyncCtx)
tại System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Object state)
tại System.Threading.ThreadHelper.ThreadStart()

Trả lời

5

Tôi bắt đầu viết một giải thích rút gọn hơn về lý do tại sao bạn KHÔNG nên có hai quy trình riêng biệt, để hỗ trợ nhận xét của tôi cho câu trả lời @stephenl được đăng. NServiceBus về cơ bản thực thi một hàng đợi đầu vào cho mỗi quá trình.

Vì vậy, thông thường, bạn sẽ có hai quy trình riêng biệt. EventAService sẽ đọc EventA từ QForEventA, trong một quá trình riêng biệt từ EventBService để đọc EventB từ QForEventB.

Sau đó, tôi đã xem xét kỹ hơn mã mẫu của bạn và nhận ra bạn đang ở trong ứng dụng Biểu mẫu Windows. Duh! Bây giờ tôi cảm thấy hơi ngu ngốc. Tất nhiên bạn chỉ có thể có một quy trình. Hãy tưởng tượng nếu sau khi khởi chạy Outlook, bạn cũng phải khởi chạy MailService.exe để thực sự nhận được thư!

Vì vậy, vấn đề thực sự là bạn có thời gian xử lý khác nhau đáng kể cho EventA và EventB trong ứng dụng Windows Forms của bạn. Tôi không có bất kỳ cách nào để biết công việc đó là gì, nhưng đây là một chút kỳ lạ đối với một ứng dụng khách.

Phần lớn thời gian đó là dịch vụ có quá trình xử lý lớn và bất kỳ tin nhắn nào mà khách hàng nhận được đều khá nhẹ - điều gì đó dọc theo dòng "Thực thể X đã thay đổi để lần sau bạn sẽ cần tải nó trực tiếp từ cơ sở dữ liệu "và xử lý nó liên quan đến việc chỉ cần bỏ một cái gì đó ra khỏi bộ nhớ cache - chắc chắn không phải là một quá trình chạy dài.

Nhưng có vẻ như vì lý do gì quá trình xử lý trong ứng dụng BẠN mất nhiều thời gian, mà trong một ứng dụng WinForms được về vì lo ngại về thread UI marshalling, ngăn chặn thread UI vv

tôi sẽ đề nghị một hệ thống nơi bạn không làm tất cả việc xử lý trong trình xử lý NServiceBus trong ứng dụng WinForms của bạn, nhưng sắp xếp nó ở một nơi khác. Đưa nó vào ThreadPool như một mục công việc, hoặc một cái gì đó như thế. Hoặc đặt các mục chạy dài vào một Hàng đợi và có một cuộc khủng hoảng chủ đề nền trên những tốc độ riêng của nó. Bằng cách đó, tất cả các trình xử lý tin nhắn NServiceBus thực hiện là "Yep, nhận được thông điệp. Cảm ơn rất nhiều." Sau đó, nó sẽ không thực sự quan trọng nếu các thông điệp NServiceBus được xử lý một tại một thời điểm.

Cập nhật:

Trong những ý kiến, OP hỏi những gì sẽ xảy ra nếu bạn ném công việc để ThreadPool sau NServiceBus finsihes nhận nó. Đó là, tất nhiên, mặt trái để tiếp cận này - sau khi NServiceBus được thực hiện, bạn đang ở trên của riêng bạn - nếu nó không thành công trong ThreadPool, sau đó nó vào bạn để tạo logic thử lại của riêng bạn, hoặc chỉ bắt ngoại lệ, cảnh báo người dùng ứng dụng WinForms và để nó chết.

Rõ ràng là tối ưu, nhưng nó đặt ra câu hỏi - chính xác là loại công việc nào bạn đang cố gắng hoàn thành trong ứng dụng WinForms? Nếu sự mạnh mẽ mà NServiceBus cung cấp (các lần thử lại tự động và hàng đợi lỗi cho các thông điệp độc) là một phần quan trọng của câu đố này, thì tại sao nó lại xuất hiện trong một ứng dụng WinForms ngay từ đầu? Logic này có thể cần được tải xuống một dịch vụ bên ngoài ứng dụng WinForms, nơi có hàng đợi riêng biệt cho từng loại thông báo (bằng cách triển khai các dịch vụ riêng biệt) trở nên dễ dàng, và chỉ những phần ảnh hưởng đến giao diện người dùng mới được gửi trở lại máy khách WinForms. Khi các tin nhắn đến giao diện người dùng chỉ ảnh hưởng đến giao diện người dùng, việc xử lý chúng hầu như luôn là tầm thường và bạn sẽ không cần phải tải xuống ThreadPool để theo kịp.

Nói trực tiếp với tình huống bạn đã mô tả trong GitHub Issue, điều này thực sự giống như loại kịch bản trong đó các quy trình riêng biệt cho từng loại thông báo chính xác là giải pháp được quy định. Tôi nghe nói rằng nó nghe có vẻ áp đảo để triển khai và quản lý nhiều quá trình đó, nhưng tôi nghĩ bạn sẽ thấy rằng nó không tệ như âm thanh. Thậm chí còn có những lợi thế - nếu bạn phải triển khai lại kết nối của mình với Amazon.com, ví dụ, bạn chỉ phải triển khai lại điểm cuối, không có thời gian chết cho bất kỳ điểm nào khác, hoặc bất kỳ lo ngại nào về các lỗi có thể đã được giới thiệu cho những người khác.

Để dễ triển khai, hy vọng bạn đang sử dụng máy chủ tích hợp liên tục và sau đó kiểm tra các công cụ như DropkicK để giúp triển khai được viết. Cá nhân, công cụ triển khai yêu thích của tôi là Robocopy cũ tốt. Ngay cả một cái gì đó đơn giản như 1) NET STOP ServiceName, 2) ROBOCOPY, 3) NET START ServiceName là khá hiệu quả.

+0

Tôi đã suy nghĩ về ném đến ThreadPool như mục công việc, nhưng nếu nó không có? Xử lý sẽ được hoàn thành công việc của nó, do đó, tin nhắn sẽ được loại bỏ khỏi hàng đợi và không có cách nào tiêu chuẩn để có được nó trở lại đó (hoặc tôi thiếu một cái gì đó?). Chúng tôi đang sử dụng các hình thức cửa sổ như một công cụ quản lý quy trình - Tôi đã đề cập đến ví dụ cụ thể hơn ở đây: https://github.com/NServiceBus/NServiceBus/issues/219 – Giedrius

+1

@Giedrius: Cung cấp thông tin cập nhật trong phần nội dung câu trả lời. –

+0

Cảm ơn sự giúp đỡ của bạn. Để trả lời câu hỏi của bạn - WinForms là để có một bảng điều khiển để tạm dừng/tiếp tục, cũng để xem tình trạng hiện tại của kênh bán hàng - đó là những gì xử lý. Chúng tôi tìm thấy một cách để có một số người nhận bằng cách sử dụng AppDomain riêng biệt, nhưng nói chung đó là cách giải quyết đau đớn. Có vẻ như chúng tôi sẽ phải chấp nhận giải pháp thay thế cho AppDomains, hoặc tìm kiếm thay thế cho NServiceBus, hoặc suy nghĩ lại triển khai (bây giờ chúng tôi có cc.net + clickOnce) và có bảng điều khiển và trình xử lý được đặt thành các phần riêng biệt. – Giedrius

2

Bạn không cần phải, bạn chỉ cần tạo một handler cho mỗi sự kiện trong máy thu. Ví dụ

public class EventAHandler : IHandleMessages<EventA>{} 

public class EventBHandler : IHandleMessages<EventB>{} 

Nếu bạn muốn hàng đợi riêng thì bạn cần phải đưa từng xử lý thành một thiết bị đầu cuối riêng biệt. Điều đó có ý nghĩa?

Ngoài ra tôi nghĩ biểu đồ của bạn cần một chút công việc. Đó là một điều ghi nhãn tôi chắc chắn, nhưng cách tôi thấy nó là Host là nhà xuất bản thực tế, không phải là các thiết bị đầu cuối của khách hàng (mà bạn đã đặt tên là Publisher A và Publisher B).

UPDATE: nó một ví dụ đơn giản nhưng minh họa những gì tôi có nghĩa là - https://github.com/sliedig/sof9411638

Tôi đã kéo dài mẫu Full Duplex mà đi kèm với NServiceBus bao gồm ba thiết bị đầu cuối bổ sung, hai trong số đó đăng ký vào các sự kiện được xuất bản bởi máy chủ tương ứng và một điểm cuối xử lý cả hai. HTH.

+0

về cách đặt tên, đó chỉ là mẫu, vì vậy có thể bạn nói đúng, những người giống như người gửi và máy chủ là nhà xuất bản. Về hàng đợi, nếu cả hai sự kiện được đẩy vào cùng một hàng đợi, không phải là nếu EventA đến trước và phải mất nhiều thời gian để xử lý nó, EventB sẽ đợi cho đến khi EventA được xử lý? Tôi nghĩ rằng nếu họ đang ở trên hàng đợi riêng biệt, họ có thể được xử lý đồng thời hoặc tôi là sai? – Giedrius

+1

Nếu bạn định cấu hình nó để sử dụng nhiều luồng, thì có thể bạn sẽ không gặp nhiều vấn đề với việc chặn chúng. Điều đó đang được nói, bạn vẫn có thể có một dòng chính của EventAs sẽ ràng buộc tất cả các chủ đề và ngăn chặn việc xử lý EventBs. Nếu đó là điều bạn quan tâm, bạn nên có một điểm cuối nhận riêng cho EventB. –

+0

Vâng, cấu hình nó để sử dụng nhiều chủ đề yêu cầu giấy phép thương mại như tôi hiểu :) Và chúng tôi không có nhiều tin nhắn, để mua giấy phép thương mại cho điều đó, chỉ EventA và EventB thời gian xử lý trung bình là rất khác nhau. Bạn có thể chỉ cho tôi mẫu của người nhận có hai thiết bị đầu cuối nhận không? – Giedrius

Các vấn đề liên quan