2013-02-27 41 views
6

Tôi có nhiều ứng dụng hiện có gửi và nhận tin nhắn bằng MSMQ qua API System.Messaging. Các hàng đợi nói chung là không giao dịch và là hỗn hợp của MSMQ 3 và 4.Tạo cơ chế thử lại trong MSMQ mà không có WCF

Ứng dụng nhận xử lý tin nhắn độc ngay bây giờ đến mức xuất hiện đầu tiên của bất kỳ ngoại lệ nào, các thông điệp được đưa vào hàng đợi lỗi để can thiệp thủ công . Nhưng nó chỉ ra rằng phần lớn các can thiệp thủ công bao gồm chỉ đơn giản là di chuyển thông điệp trở lại hàng đợi chính cho một thử tại thời điểm nó thành công. Vì vậy, để tự động hóa quá trình đó, tôi muốn thêm một tính năng thử lại cho người nhận sao cho các tin nhắn được chuyển trở lại hàng đợi chính một số lần nhất định với một độ trễ nhất định giữa mỗi lần.

Thay vì phát minh lại bánh xe, tôi muốn tận dụng mọi thứ mà MSMQ có thể cung cấp ra khỏi hộp cũng như bất kỳ mẫu thực hành phổ biến hoặc tốt nhất nào về điều này. Để kết thúc, có rất nhiều ra có về sự hỗ trợ bổ sung cho các thông điệp độc trong MSMQ 4. Nhưng họ dường như không dễ dàng truy cập thông qua. Net. Hơn nữa, các tài liệu tham khảo duy nhất tôi có thể tìm thấy để sử dụng chúng là thông qua WCF với một ràng buộc MSMQ.

Bất kỳ ai có thể đề xuất bất kỳ mẫu nào hoặc chỉ ra bất kỳ ví dụ nào triển khai thử lại nếu một trong số đó không sử dụng WCF?

Trả lời

7

Tôi không thể tìm thấy một mẫu đơn phổ biến để thực hiện việc này. Nhưng sau khi poking xung quanh một chút trong System.Messaging, tôi đã có thể tận dụng đặc tính Message và MSMQ hành vi trong những gì tôi nghĩ là một cách thích hợp để có được công việc làm với tối thiểu của các bộ phận chuyển động.

Dưới đây là những gì tôi đã triển khai.Hóa ra là khá đơn giản và nhẹ - không nhiều mã và dễ bảo trì:

Tôi tạo ra một đối tượng gọi RetryLevel rằng có ba thuộc tính:

int Trình tự, int NumberOfRetries, TimeSpan trễ

Cấu hình của ứng dụng máy thu hiện có danh sách RetryLevel. Vì vậy, tính năng mới về cơ bản hỗ trợ thử lại ở cấp độ n.

Sau đó, tôi đã tạo một đối tượng có tên là RetryInfo. Đối tượng này có hai đặc tính:

int Nỗ lực, chuỗi SourceQueuePath

Một thể hiện của đối tượng RetryInfo là serialized và lưu trữ trong tài sản của mỗi tin nhắn mà kết thúc lên được thử lại Extension. Điều này cho phép tôi theo dõi trạng thái thử lại hiện tại trên chính thư, do đó loại bỏ sự cần thiết phải duy trì một kho lưu trữ siêu dữ liệu thử lại riêng biệt và tất cả các phí trên sao chép các Id tin nhắn, giữ cho dữ liệu được đồng bộ hóa, v.v.

Cuối cùng, tôi đã thêm một đường dẫn chờ đợi đến cấu hình của người nhận. Hàng đợi này là nơi thư sẽ bị xóa trong khi chúng ở trong "thời gian chờ". Vì vậy, bây giờ, khi một trình xử lý tin nhắn từ chối một tin nhắn, người nhận deserializes nó RetryInfo, nếu có một, và nhìn vào số (trước) Những nỗ lực để xác định RetryLevels cấu hình nó đã đạt được.

Người nhận sau đó đặt thuộc tính TimeToBeRecRecieved (TTBR) của Message thành DateTime.Now cộng với giá trị Trì hoãn của RetryLevel thích hợp. Sau đó, nó đặt thuộc tính AdministrativeQueue thành một Hàng đợi được tạo từ thuộc tính SourceQueuePath của RetryInfo và đặt Kiểu xác nhận của Message thành AcknowledgeTypes.NegativeReceive. Cuối cùng, nó đặt Thông báo trên hàng chờ.

Từ đây, MSMQ xem TTBR của Thư. Khi nó lần ra, MSMQ đặt thông điệp trở lại trên hàng đợi trong tài sản AdministrativeQueue của nó, đó là hàng đợi thông điệp ban đầu đến từ đó. Nếu tin nhắn tiếp tục bị từ chối bởi các trình xử lý, nó chỉ di chuyển theo cách của nó lên RetryLevels.

Nếu nỗ lực của thông báo vượt quá tất cả các NumberOfRetries trên cấu hình RetryLevels, thuộc tính TTBR của tin nhắn được đặt thành TimeSpan.Zero, thuộc tính UseDeadLetterQueue được đặt thành true và thông báo được đặt trên hàng chờ đợi giống như bất kỳ thử lại khác. Lần này, tuy nhiên, nó lần ra ngay lập tức và MSMQ tàu nó vào hàng đợi thư chờ đợi của hệ thống máy chủ chờ đợi (DLQ), nơi nó có thể được xử lý bằng tay.

0

Khi bạn nói bạn không muốn phát minh lại bánh xe, tôi khuyên bạn nên sử dụng một trong nhiều khung công tác có sẵn như MassTransit hoặc các khung công cụ khác.

Cá nhân, tôi đã có trải nghiệm tích cực với NServiceBus, nằm trên đầu trang của MSMQ.

Điều này giúp cấu hình xử lý lỗi khá dễ dàng. Bạn có thể xác định hàng đợi làm việc thực tế cho ứng dụng của mình và bạn có thể định nghĩa thêm một hàng đợi lỗi chuyên dụng. Ngoài ra, bạn cấu hình bao nhiêu lần thử ứng dụng sẽ - tự động và hoàn toàn minh bạch cho mã của bạn - cố gắng cho đến khi nó di chuyển thông điệp độc vào hàng đợi bạn chọn.

Điều này cho phép bạn dễ dàng cấu hình một cái gì đó như: "Nếu tôi không thể xử lý thông điệp này một cách chính xác trong vòng 5 lần thử lại, sau đó di chuyển nó vào hàng đợi lỗi của tôi"

Đây là một out-of-the-box chức năng.

cấu hình Ví dụ (từ tài liệu chính thức), lưu ý các app.config của Publisher phần:

Basic Publisher/Subscriber configuration from official documentation http://images.nservicebus.com/basic_pubsub.png

Đối với các phần không WCF, NServiceBus hoạt động giống như tốt cho bất kỳ ứng dụng .NET. Bạn có sự lựa chọn để chỉ đơn giản là tham khảo các DLL, hoặc bạn có thể sử dụng NServiceBus như một container để lưu trữ ứng dụng của bạn như một dịch vụ địa phương, hoặc bạn có thể đăng ký nó vĩnh viễn như một dịch vụ windows. Và cuối cùng, nếu một ngày nào đó bạn sẽ đổi ý, và chuyển sang WCF cũng sẽ được hỗ trợ. :-)

+0

Cảm ơn Jens. Tôi biết về NServiceBus và MassTransit giống như WCF, các ứng dụng được xây dựng trên MSMQ có chức năng thử lại. Nhưng câu hỏi của tôi là một cách tốt để tạo ra chức năng thử lại nếu bạn đang xây dựng một ứng dụng trên đầu trang của MSMQ là gì. Không phải cách tốt để thay thế đơn đăng ký của tôi với ứng dụng khác là gì. –