2009-06-24 12 views
7

Piszę aplikację .NET Windows Forms, która opublikuje komunikat w kolejce Msp Websphere, a następnie odpytuje inną kolejkę odpowiedzi. Jeśli odpowiedź zostanie zwrócona, aplikacja częściowo przetworzy odpowiedź w czasie rzeczywistym. Ale odpowiedź musi pozostać w kolejce, aby codzienne zadanie wsadowe, które również odczytywało z kolejki odpowiedzi, może wykonać resztę przetwarzania.Jak przeglądać wiadomość Websphere MQ bez jej usuwania?

Doszedłem aż do przeczytania wiadomości. To, czego nie byłem w stanie wymyślić, to jak go przeczytać bez usuwania go.

Oto, co mam do tej pory. Jestem nowicjuszem MQ, więc wszelkie sugestie zostaną docenione. I nie wahaj się odpowiedzieć w języku C#.

Public Function GetMessage(ByVal msgID As String) As MQMessage 
    Dim q = ConnectToResponseQueue() 
    Dim msg As New MQMessage() 
    Dim getOpts As New MQGetMessageOptions() 
    Dim runThru = Now.AddMilliseconds(CInt(ConfigurationManager.AppSettings("responseTimeoutMS"))) 
    System.Threading.Thread.Sleep(1000) 'Wait for one second before checking for the first response' 
    While True 
     Try 
      q.Get(msg, getOpts) 
      Return msg 
     Catch ex As MQException When ex.Reason = MQC.MQRC_NO_MSG_AVAILABLE 
      If Now > runThru Then Throw ex 
      System.Threading.Thread.Sleep(3000) 
     Finally 
      q.Close() 
     End Try 
    End While 
    Return Nothing 'Should never reach here' 
End Function 

UWAGA: I nie sprawdzili, że mój kod faktycznie usuwa wiadomość. Ale w ten sposób rozumiem MQ do pracy i wydaje się, że to właśnie się dzieje. Proszę mnie poprawić, jeśli to nie jest domyślne zachowanie.

+0

+1 - Żałuję, że nie odkryłem tego pytania, zanim musiałem sam się o tym przekonać. –

Odpowiedz

11

Należy otworzyć kolejkę za pomocą opcji MQOO_BROWSE. Następnie podczas pierwszego czytania wykonujesz GET, używając opcji MQGMO_BROWSE_FIRST. Wreszcie, twoje następne GET-y powinny korzystać z opcji MQGMO_BROWSE_NEXT.

Uwaga: MQOO to opcje otwarte MQ, a MQGMO to MQ. Opcje wiadomości.

+0

To się udało. Wielkie dzięki. –

+0

Doskonała odpowiedź. To uratowało mi dzisiaj bekon. Dziękuję Ci. – duffymo

1

Naprawdę powinieneś robić to z oddzielnymi kolejkami. Przetwarzanie na koniec dnia powinno mieć własną kolejkę. Po przetworzeniu części wiadomości zostanie ona wysłana do kolejki EOD.

Za pomocą opcji Przeglądaj będziesz musiał śledzić, które wiadomości już gdzieś przetworzyłeś.

Można również ustawić limit czasu oczekiwania na GET. Nie musisz więc "czekać 1 sekundy przed sprawdzeniem kolejki". Jak napisano w tej chwili, nie możesz trafić w stan braku msg, ponieważ nie ustawiłeś NOWAIT w opcjach wiadomości get.

+0

+1 Dobry punkt. W swoim poście nie wspomniałem, że robię jedną prośbę i odpowiedź na raz. Identyfikator korelacji odpowiedzi będzie zgodny z identyfikatorem komunikatu żądania, więc śledzenie wiadomości, które już przetworzyłem, nie powinno stanowić problemu. Jeśli chodzi o czas oczekiwania, to widziałem, ale nie wiedziałem, co z tym zrobić. Zrobiłem więcej badań w oparciu o twoją sugestię i znacznie oczyściłem tę metodę za pomocą tego podejścia. Wielkie dzięki! –

1

Dla dobra potomności, tutaj jest (myślę) znacznie ulepszona wersja metody opartej na mamboking i odpowiedziach jmucchiello.

Public Function GetMessage(ByVal correlID As Byte()) As MQMessage 
    Dim waitInterval = CInt(ConfigurationManager.AppSettings("responseTimeoutMS")) 
    Dim q As MQQueue = Nothing 
    Try 
     Dim msg As New MQMessage() 
     Dim getOpts As New MQGetMessageOptions() 
     q = ConnectToResponseQueue() 
     msg.MessageId = MQC.MQMI_NONE 
     msg.CorrelationId = correlID 
     getOpts.MatchOptions = MQC.MQMO_MATCH_CORREL_ID 
     getOpts.WaitInterval = waitInterval 
     getOpts.Options = MQC.MQGMO_BROWSE_FIRST Or MQC.MQGMO_WAIT 
     q.Get(msg, getOpts) 
     Return msg 
    Finally 
     If q IsNot Nothing AndAlso q.IsOpen() Then q.Close() 
    End Try 
End Function 
1

Zdaję sobie sprawę, że przychodzę do tej dyskusji nieco późno i prawdopodobnie już zakodowałeś tę aplikację. Jeśli kiedykolwiek będziesz musiał go zmodyfikować lub dla kogokolwiek, kto może potrzebować czegoś podobnego, mam kilka obserwacji.

Po pierwsze, jeśli można to zrobić z klientem WMM v7 QMgr i v7, byłoby to preferowane rozwiązanie. W wersji 7 obsługa .Net została przeniesiona z SupportPac do części produktu podstawowego. Istnieje znaczna nowa funkcjonalność, niektóre poprawki błędów i lepsza wydajność. Również na v7 możesz użyć pub-sub ..., który doprowadza mnie do mojej drugiej obserwacji.

Na podstawie opisu w oryginalnym poście, zrobiłbym to w Pub-Sub. Aplikacja, która umieszcza komunikat, potrzebuje tylko jednego i nie musi nawet wiedzieć, że chodzi o temat. Można rzeczywiście umieścić alias na temat, który sprawia, że ​​wygląda on jak kolejka do producenta wiadomości. Twoje konsumujące aplikacje mogą następnie subskrybować lub możesz zrobić dwie subskrypcje administracyjne, tak aby opublikowane wiadomości trafiały do ​​dwóch ustawionych kolejek. Twoje aplikacje mają wtedy dedykowaną kolejkę i nie ma żadnych zmian w kodowaniu dla producenta i aplikacji wsadowej, to tylko konfiguracja. Oczywiście aplikacja sterująca transakcjami musi raczej konsumować wiadomości niż je przeglądać.

Tutejsze zalety są różnorakie:

  • Ponieważ kolejka wypełnia się z wiadomości, indeksowanie zostaje przepłukany na dysku i powyżej progu zobaczysz spadek wydajności, które mogą być znaczące. Dlatego obecna metoda nie skaluje się tak dobrze.
  • Za pomocą metody pub-sub można mieć wiele instancji aplikacji czasu rzeczywistego lub aplikacji wsadowych lub obu, a te mogą być na tym samym lub innym QMgr. Skalowanie jest łatwe.
  • Eliminujesz zależność między aplikacjami w czasie rzeczywistym i aplikacjami wsadowymi, które muszą być na tym samym QMgr.
  • Bardziej przejrzysta administracja. Jeśli widzisz wiadomości budowane w kolejce w czasie rzeczywistym, wiesz, że masz problem.

Kilka zupełnie różnych zagadnień również tutaj. Jedną z nich jest użycie opcji Fail if Quiescing. Celem tego jest to, że gdy QMgr zostanie całkowicie zamknięty, ta opcja powoduje, że twoje wywołanie API kończy się z kodem zwrotnym wskazującym, że QMgr jest wyłączany. Jeśli nie uwzględnisz tej opcji, możliwe jest, że w przypadku dwóch lub więcej połączonych aplikacji QMgr będzie się wyłączał w sposób czysty i trzeba go będzie wymusić, lub jeśli jego procesy zostaną zabite za pomocą brutalnej siły. Z reguły zawsze używaj polecenia "Fail", jeśli wypisujesz wszystkie wywołania API, które go obsługują. Powodem, dla którego w ogóle istnieje, jest dla ludzi, którzy potrzebują transakcji XA, ale z jakiegoś powodu nie mogą z niego korzystać. W tym scenariuszu połączenie CONNECT i pierwsze wywołanie GET lub PUT używa parametru Fail, jeśli ustawienie Quiescing jest ustawione, a kolejne operacje GET lub PUT nie. Powoduje to, że QMgr oczekuje na zakończenie całego zestawu wywołań GET/PUT, ale następny CONNECT lub GET/PUT używa Fail, jeśli Quiescing, więc QMgr ma szansę na wyłączenie, jeśli to konieczne.

Inną obserwacją tutaj jest to, że tutaj nie ma tu Złodzieja. Zgaduję, że jest jeszcze jeden w zasięgu stosu połączeń? Zawsze zaleca się wydrukowanie kodu powrotu WMQ z wyjątku, aby można było znaleźć przyczynę. W przypadku zadań konsultingowych zawsze doradzam klientom, że niepowodzenie drukowania kodu powrotu (lub powiązany wyjątek dla kodu JMS/XMS) jest elementem showstopper, który powinien uniemożliwić promowanie aplikacji do Produkcji. To naprawdę takie ważne. Nawet jeśli złapiesz kod, który wywołuje metodę getMessage(), ktoś wykorzystujący przykładowy fragment kodu może nie zdawać sobie sprawy z tego, że brakuje tego ważnego elementu.

Powiązane problemy