2013-02-27 13 views
6

Mam wiele istniejących aplikacji, które wysyłają i odbierają wiadomości za pomocą MSMQ za pośrednictwem interfejsu API System.Messaging. Kolejki są generalnie nietransakcyjne i są mieszanką MSMQ 3 i 4.Tworzenie mechanizmu ponawiania w MSMQ bez WCF

Aplikacje odbierające obsługują wiadomości trucizny w takim stopniu, że przy pierwszym wystąpieniu dowolnego wyjątku komunikaty są umieszczane w kolejce błędów w celu ręcznej interwencji . Okazuje się jednak, że zdecydowana większość ręcznej interwencji polega po prostu na przeniesieniu wiadomości z powrotem do głównej kolejki, aby spróbować jeszcze raz, kiedy to się uda. Aby zautomatyzować ten proces, chcę dodać do odbiornika funkcję ponawiania, tak aby komunikaty były przenoszone z powrotem do głównej kolejki określoną liczbę razy z określonym opóźnieniem między nimi.

Zamiast odkrywać nowe koło, chcę wykorzystać wszystko, co tylko możliwe, że MSMQ dostarcza z pudełka, jak również wszelkie popularne wzorce najlepszych praktyk. W tym celu jest wiele informacji na temat dodatkowego wsparcia dla wiadomości trucizny w MSMQ 4. Nie wydają się jednak łatwo dostępne przez .Net. Ponadto, jedynymi odniesieniami, jakie mogę znaleźć przy ich użyciu, jest WCF z wiązaniem MSMQ.

Czy ktoś może sugerować wzorce lub wskazywać przykłady, które implementują ponowić próbę, jeśli nie używa się WCF?

Odpowiedz

7

Nie mogłem znaleźć jednego, popularnego wzoru do robienia tego. Ale po odgadnięciu trochę w System.Messaging, byłem w stanie wykorzystać właściwości wiadomości i zachowanie MSMQ w tym, co uważam za odpowiedni sposób na wykonanie pracy przy minimalnych ruchomych częściach.

Oto, co zaimplementowałem.Okazało się to być dość prosty i lekki - nie dużo kodu i łatwe w utrzymaniu:

stworzyłem obiekt o nazwie RetryLevel który ma trzy właściwości:

int kolejności, int NumberOfRetries, TimeSpan Delay

Konfiguracja aplikacji odbiorcy zawiera teraz listę RetryLevel. Tak więc nowa funkcja zasadniczo obsługuje ponowna próba na poziomie n.

Następnie utworzyłem obiekt o nazwie RetryInfo. Ten obiekt posiada dwie właściwości:

int próbach ciąg SourceQueuePath

Instancja obiektu RetryInfo jest seryjny i przechowywane we właściwości Extension każdej wiadomości, że kończy się ich ponowiona. To pozwala mi śledzić bieżący stan ponawiania na samym komunikacie, eliminując w ten sposób konieczność utrzymywania oddzielnego magazynu metadanych ponawiania i całego obciążenia związanego z uzgadnianiem identyfikatorów wiadomości, utrzymywania synchronizacji danych itp.

Wreszcie dodałem ścieżka kolejki oczekiwania do konfiguracji odbiornika. Ta kolejka jest miejscem, w którym wiadomości zostaną usunięte, gdy są w "limicie czasu".

Tak więc teraz, gdy program obsługi wiadomości odrzuca komunikat, odbiornik deserializuje jego RetryInfo, jeśli taki istnieje, i sprawdza liczbę (poprzednich) prób ustalenia, które ze skonfigurowanych poziomów RetryLevel osiągnęło.

Odbiornik ustawia właściwość TimeToBeRecieved (TTBR) komunikatu na DateTime.Now oraz wartość opóźnienia odpowiedniej opcji RetryLevel. Następnie ustawia właściwość AdministrativeQueue na kolejkę utworzoną z właściwości SourceQueuePath obiektu RetryInfo i ustawia właściwość Message's AcknowledgeType na AcknowledgeTypes.NegativeReceive. W końcu umieszcza komunikat w kolejce oczekiwania.

Stąd MSMQ ogląda TTBR wiadomości. Po przekroczeniu limitu czasu usługa MSMQ umieszcza komunikat w kolejce w jego właściwości AdministrativeQueue, która jest kolejką, z której pochodzi pierwotnie wiadomość. Jeśli komunikat nadal będzie odrzucany przez procedury obsługi, to po prostu przesuwa się w górę do poziomu RetryLevels.

Jeżeli Próby wiadomość jest poza tym wszystkich NumberOfRetries od skonfigurowanego RetryLevels, nieruchomości TTBR depeszy jest ustawiony na TimeSpan.Zero właściwość UseDeadLetterQueue jest ustawiona na wartość true, a wiadomość jest umieszczany w kolejce oczekiwania tak jak każdy inne próby. Tym razem jednak upływa natychmiast i MSMQ wysyła je do kolejki martwych liter hosta kolejki oczekującej (DLQ), gdzie można ją obsługiwać ręcznie.

0

Mówiąc, że nie chcesz ponownie wymyślać koła, sugeruję użycie jednego z wielu dostępnych frameworków, takich jak MassTransit lub innych.

Osobiście zrobiłem pozytywne wrażenia z NServiceBus, który znajduje się na szczycie MSMQ.

Ułatwia to konfigurowanie obsługi błędów. Możesz zdefiniować rzeczywistą kolejkę roboczą dla swojej aplikacji i możesz dodatkowo zdefiniować dedykowaną kolejkę błędów. Możesz także skonfigurować liczbę prób, które aplikacja będzie - automatycznie i całkowicie przezroczysta dla twojego kodu - próbować, dopóki nie przeniesie komunikatu o truciźnie do wybranej kolejki.

Pozwala to łatwo skonfigurować coś takiego: „Gdybym nie może przetworzyć tę wiadomość poprawnie ciągu 5 prób, a następnie przenieść go do mojego kolejki błędów

To jest out-of-the-box funkcjonalność.

Przykład konfiguracji (z oficjalnej dokumentacji) należy zwrócić uwagę na app.config z Publisher części:

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

Co do części non-WCF, NServiceBus działa równie dobrze dla każdej aplikacji .NET. Masz wybór, aby po prostu odwołać się do bibliotek DLL lub możesz użyć NServiceBus jako kontener do obsługi aplikacji jako usługi lokalnej lub możesz zarejestrować ją na stałe jako usługę Windows. I na koniec, jeśli kiedyś zmienisz zdanie, i przełączysz się na WCF, który również będzie obsługiwany. :-)

+0

Dzięki Jens. Jestem świadomy NServiceBus i MassTransit, które są, podobnie jak WCF, aplikacjami zbudowanymi na MSMQ, które mają funkcję ponowienia. Ale moje pytanie brzmi: jaki jest dobry sposób tworzenia funkcji ponawiania, jeśli budujesz aplikację na MSMQ. Nie jest to dobry sposób na zastąpienie mojej aplikacji innym. –