![]() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| C/C++ / CGI / Sieć Novell / PHP / Java / SQL / Oracle / WebSphere MQ / WebSphere Message Broker / JavaScript / Humor / IT Quiz | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
|
![]() |
Informacje podstawowe O WebSphere Message Broker *Agregacja *Nody HTTP *Nody HTTP i SSL Web Services i Basic-Auth Publish/Subscribe Error Handling *Manipulowanie treścią komunikatu *Referencje *Trace Debuging Współdzielenie danych w ramach przepływu Operacje na bazie danych Parametry UDP Nod MQGet *Nody typu Timer Własne nody JAVA *Wywołanie kodu JAVA z ESQL Modyfikacja parametrów pliku BAR *CVS runtime versioning i keywords Dostępne parametry brokera * Accounting and Statistics Security Configuration Manager Proxy Wydajność Literatura Jeden plik Legenda w przygotowaniu * w trakcie tworzenia Podczas tego kursu postaram się omówić narzędzie WebSphere Message Broker firmy IBM. Kurs ten jest w trakcie tworzenia i może się zdarzyć, że informacje w nim zawarte mogą wydawać się chaotycznie posegregowane. Nie będzie on również omawiał narzędzia od podstaw, lecz najciekawsze według mnie jego elementy, dlatego może się okazać, że dla osób nie znających chociaż podstaw WebSphere Message Broker będzie on niezrozumiały. Będę starał się cały czas rozwijać go, ponieważ jest to moja specjalizacja (systemy kolejkowe) i docelowo kurs ten będzie zawierał podstawowe informacje jak również zaawansowane dla osób znających temat. Na dzień dzisiejszy jest w nim trochę informacji podstawowych oraz trochę informacji wchodzących głębiej w charakterystykę narzędzia. Agregacja jest ciekawą technika pozwalającą na wysłaniu z przepływu kilku zapytań, agregacji odpowiedzi, a następnie na podstawie odebranych odpowiedzi przygotowanie zagregowanej odpowiedzi. Do obsługi agregacji wykorzystujemy nody AggregateControl, AgregateRequest oraz AggregateReply. Nod AggregateControl służy do zaznaczenia rozpoczęcia procesu agregacji. Najważniejsze parametry noda ta: Aggregate name : nazwa agregacji (unikalny identyfikator) Timeout : czas jaki będziemy oczekiwać na odpowiedź Nod AgregateRequest służy do określenia komunikatu MQ, który jest częścią procesu agregacji. Umieszcza się go za node MQOutput aby zapisać informacje o tym na jakie pytania w procesie agregacji oczekujemy odpowiedzi. Najważniejszy parametr noda to: Folder name : Folder, w którym będzie zapisana odpowiedz (unikalny identyfikator zapytania w ramach agregacji) Nod AggregateReply służy do magazynowania odpowiedzi w ramach agregacji i w efekcie zwraca drzewo, ze wszystkimi odpowiedziami. Najważniejsze parametry noda to: Aggregate name nazwa agregacji (unikalny identyfikator) skorelowany z tym samym parametrem noda AggregateControl Unknow message timeout określa w sekundach czas jaki proces oczekuje w przypadku odczytania komunikatu, które nie może skorelować z żadnym z wysłanych wcześniej zapytań zanim wyśle go do terminala "Unknown" Najważniejsze terminale noda to: Failure : standardowy terminal do którego przekazywane są komunikaty, które spowodowały bład w procesowaniu Unknown : do tego terminala przekazywane są komunikaty, które nie można skorelować z żadnym wysłanym wcześniej zapytaniem Out : do tego terminala przekazywany jest komunikat grugujące wszystkie zebrane odpowiedzi Timeout : do tego terminala przekazywany jest komunikat grupujący wszystkie odpowiedzi ( które nadeszły w zakładnym czasie określonym na nodzie AggregateControl) Poniżej postaram się przedstawić scenariusz opisujący wykorzystanie agregacji w praktyce. Zaimplementujemy przepływ będący WebServices, którego zadaniem będzie zwrócenie liczby. WebService przygotuje i wyśle dwa zapytania MQ. Na każde zapytanie MQ otrzymamy w odpowiedzi liczbę. Zadaniem WebSevice jest zsumowanie tych liczb i zwrócenie tej sumy jako odpowiedzi WS. Pierwszym elementem przepływu jest nod HTTPInput oczekujący na połączenia WS. Dalej mamy nod AggregateControl, którego ustawiamy parametr Aggregate name na Aggr oraz Timeout na 15 sekund. W ten sposób określiliśmy identyfikator dla agregacji oraz określiliśmy skończony czas jaki oczekujemy na odpowiedź. Dalej mamy nod Compute, którego zadaniem jest przygotowanie komunikatów MQ W pierwszej części w module deklarujemy namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; CREATE FUNCTION PrepareMQMDRequest() Dalej w głónej funkcji Main w pierwszej części tworzymy odpowiednie domeny MQMD oraz XMLNS, usuwamy niepotrzebne elementy HTTPInputHeader oraz MRM, wywołujemy funkcje PrepareMQMDRequest wypełniającą odpowiednie pola MQMD, przygotowujemy dane komunikatu MQ na podstawie danych wejściowych. oraz propagujemy komunikat do terminala out1. CREATE NEXTSIBLING OF OutputRoot.Properties DOMAIN 'MQMD'; W ten sposób przygotowaliśmy pierwszy komunikat, który będzie wysłany do pierwszej aplikacji. Dalej przygotowujemy drugi komunikat, wywołujemy funkcje PrepareMQMDRequest wypełniającą odpowiednie pola MQMD, przygotowujemy dane komunikatu MQ na podstawie danych wejściowych. oraz propagujemy komunikat do terminala out2. CALL PrepareMQMDRequest() ; Dalej musimy jeszcze utworzyć komunikat, który będzie zawierał informacje o identyfikatorze zapytania WS.Ten identyfikator będzie nam potrzebny później w celu skorelowania przygotowywanej odpowiedzi z zapytaniem WS. Aby to zrobić wywołujemy funkcje PrepareMQMDRequest wypełniającą odpowiednie pola MQMD, przygotowujemy treść komunikatu uzupełniając go o przeczytany identyfikator zapytania WS. Następnie ustawiamy typ komunikatu na 2 czyli REPLY, propagujemy komunikat do terminala out oraz zwracamy w funkcji wartość FALSE. CALL PrepareMQMDRequest(); Dalej za każdym wymienionym wcześniej nodem MQOutput znajduje się nod AggregateRequest. Ich parametr Folder name ustawiony jest odpowiednio REQ1 dla kolejki 1, REQ2 dla kolejki 2 oraz HTTP dla kolejki HTTP. W ten sposób wysłaliśmy odpowiednie komunikaty oraz określiliśmy, że na agregacje składają sie 3 powyższe zapytania MQ. W drugiej części przepływu mamy dwa nody MQInput, jeden oczekujący na kolejce, w której mają pojawić się odpowiedzi od obu aplikacji oraz drugi na kolejce zawierającej identyfikatory zapytań WS. Nod MQInput związany z HTTP połączony jest z nodem Compute. Zadaniem tego noda jest przepisania pola MsgId do CorrelId. Pozwoli to poprawnie zidentyfikować komunikat jako odpowiedz na wysłany wcześniej komunikat. SET OutputRoot.MQMD.CorrelId=InputRoot.MQMD.MsgId; Powyższy nod Compute oraz drugi nod MQInput związany z odpowiedziami z aplikacji połączony jest z nodem AggregateReply. Zadaniem tego noda jest magazynowanie napływających odpowiedzi danej agregacji. Parametr "Aggregate name" tego noda ustawiamy na Aggr, parametr "Unknow message timeout" na 0.Jeśli nod ten w zadanym czasie określonym wcześniej w nodzie AggregateControl zbierze wszystkie odpowiedzi procesowanie przejdzie do terminala "out". Terminal ten połączony jest z nodem Compute. W pierwszej części w module deklarujemy namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; DECLARE response1 INTEGER; SET OutputRoot.MRM.soapenv:Body.tns:addIntResponse.tns:addIntResult.v= Jeśli z kolej nod AggregateReply nie zdoła w zadanym czasie określonym wcześniej w nodzie AggregateControl zebrać wszystkich odpowiedzi procesowanie z noda przejdzie do terminala "Timeout". Tutaj mogliśmy oczywiście wysłać odpowiedz WS mówiący o błędzie.W naszym scenariuszu zdecydowałem się wysłać odpowiedź na podstawie tylko zebranych odpowiedzi. W związku z tym terminal "Timeout" noda AggregateReply podłączamy do noda Compute, którego zadaniem jest przygotowanie odpowiedniej odpowiedzi WS. W pierwszej części w module deklarujemy namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; DECLARE response1 INTEGER; SET OutputRoot.Properties = InputRoot.Properties; Message Broker posiada nody odpowiadające za komunikacje HTTP z i do Brokera.Nody te to: HTTPRequest Nod ten pozwala z brokera odpytać się zewnętrznego zasobu za pomocą HTTP. HTTPInput Nod ten pozwala na implementacje HTTP przez broker. Oczekuje on na zapytania HTTP z zewnątrz. HTTPReply Nod ten jest związany z HTTPInput i pozwala na wysłanie odpowiedzi HTTP po wcześniejszym przeprocesowaniuzapytania, które dotarło do noda HTTPInput. Najważniejsze parametry noda HTTPRequest to: Web Service URL Parametr ten określa URL zdalnego Web Service. Jeśli chcemy możemy ta wartość ustawić dynamicznie w kodzie : SET OutputLocalEnvironment.Destination.HTTP.RequestURL='http://...'; Message Domain Określa domenę przy parsowaniu. Możliwe opcje to XML, XMLNS, MRM i inne. Message Set Jeśli domenę określimy jako MRM, w tym polu wybieramy Message Set. Najważniejsze parametry noda HTTPInput to: Path suffic for URL Parametr ten określa URL pod jakim oczekujemy połączeń HTTP Message Domain Określa domenę przy parsowaniu. Możliwe opcje to XML, XMLNS, MRM i inne. Message Set Jeśli domenę określimy jako MRM, w tym polu wybieramy Message Set. Nod HTTPReply służy tylko i wyłącznie do wysłania odpowiedzi HTTP. Nie ma zbyt wielu opcji. Najciekawsze to te związane z timeoutami. Poniżej postaram się zebrać kilka możliwych scenariuszy wykorzystania nodów w przepływie. W tym scenariuszu zaimplementujemy WebService na brokerze. Będzie to prosty WebService, który będzie sumował dwie liczby i zwracał ich sumę. W tym scenariuszu przepływ będzie zawierał nod HTTPInput, Compute oraz HTTPReply. Jako domenę w nodzie HTTPInput ustawiamy MRM. CREATE COMPUTE MODULE WebServiceInput_Compute Pierwszym elementem w przepływie będzie nod MQInput pobierający komunikaty MQ z kolejki. Następnie znajduje się nod Compute. W pierwszej części w module deklarujemy namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; CREATE FUNCTION processAddIntRequest() CALL CopyEntireMessage(); CALL processAddIntRequest(); W pierwszej części w module deklarujemy ponownie namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; CREATE FUNCTION processAddIntResponse() CALL CopyEntireMessage(); Dalej w funkcji Main usuwamy niepotrzebne już bloki danych HTTPRequestHeader, MRM, HTTPResponseHeader SET OutputRoot.HTTPRequestHeader=null; W kolejnej części funkcji Main tworzymy domenę MQMD zaraz po loku Properties, kopiujemy do bloku MQMD wcześniej zapisany w Environment blok myMQMD, ustawiamy parametr MsgType na MQMT_REPLY, parametr CorrelId na podstawie wejściowego MsgId, ustawiamy cel komunikatu oraz wywołujemy wcześniej zadeklarowaną funkcje processAddIntResponse. CREATE NEXTSIBLING OF OutputRoot.Properties DOMAIN 'MQMD'; Dalej w przepływie mamy nod MQOutput ustawiony parametr Destination mode na Destination List, który wyśle odpowiedź MQ do odpowiednio zadeklarowanej wcześniej kolejki. W tym scenariuszu na brokerze będzie zdeployowany WebService, który na podstawie danych wejściowych będzie zapytanie wysyłał do odpowiedniej kolejki MQ i z drugiej strony będzie oczekiwał na odpowiedź MQ. Po otrzymaniu odpowiedzi MQ przepływ bedzie wysyłał odpowiedz WebService. Pierwszym elementem przepływu jest nod HTTPInput, którego zadaniem jest oczekiwanie na zapytania WebService. Następnym elementem jest nod Compute, którego zadaniem jest przygotowanie komunikatu MQ. W pierwszej części w module deklarujemy ponownie namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; CREATE NEXTSIBLING OF OutputRoot.Properties DOMAIN 'MQMD'; Następnie usuwamy pola Properties związane z WebService, ustawiamy odpowiednie pola MQMD, tworzymy zapytanie MQ na podstawie danych wejściowych i usuwamy zbędne pola HTTPInputHeader oraz MRM. SET OutputRoot.Properties.MessageSet = ''; Następnie w przepływie znajduje się nod MQOutput, który wysyła zapytanie do aplikacji MQ, a zaraz za nim nod Compute, którego zadaniem jest wrzucenie dodatkowego komunikatu MQ zawierającego identyfikator zapytania WebServices do kolejki. W module Compute w pierwszej częsci kopiujemy Properties, MQMD oraz wskazujemy kolejkę w której zapisywane są identyfikatory zapytania WebService. SET OutputRoot.Properties = InputRoot.Properties; Następnie ustawiamy pole CorrelId komunikaty HTTP przepisując pole MsgId z wcześniej wysłanego komunikatu do kolejki aplikacyjnej oraz tworzymy treść komunikatu zawierającego identyfikator zapytania WebService. SET OutputRoot.MQMD.CorrelId= InputLocalEnvironment.WrittenDestination.MQ.DestinationData.msgId; Następnie mamy nod MQOutput którego zadaniem jest wrzucenie komunikatu do dedykowanej kolejki HTTP. Druga część przepływu odpowiada za odebranie komunikatu MQ odpowiedzi skorelowaniu go z komunikatem zawierającym identyfikator HTTP i wysłaniu odpowiedzi WebService do pytającego. Pierwszym elementem tej części jest nod MQInput oczekujący na kolejce w której pojawiają się odpowiedzi z aplikacji. Zaraz za nim jest nod MQGet z odpowiednio ustawionym parametrem wait interval oraz zaznaczonym polu Get By correlation ID i oczekującym na kolejce HTTP. Oznacza to, że nod pobierze z kolejki tylko komunikat którego Correlation Id jest identyczne jak Correlation Id odczytanego komunikatu odpowiedzi MQ. Jeśli aplikacja MQ ustawi Correlation Id odpowiedzi wstawiając w to miejsce message Id zapytania to nod MQGet zwróci odpowiedni komunikat HTTP. Po wyjściu z noda jeśli odczyta on komunikat procesowanie trafi do noda Compute. W pierwszej części w module znów deklarujemy namespaces używane w WebService DECLARE tns NAMESPACE 'http://www.myserver.com.pl/WSPilot/SimpleTypes'; SET OutputRoot.Properties = InputRoot.Properties; Następnie przepływ kończymy nodem HTTPReply wysyłającym odpowiedź WebService. Parametr noda HTTPInput mówiący o tym, że obsługuje on komunikacje szyfrowaną to Use HTTPS w zakładce Basic.Niestety tylko to nie wystarczy do bezproblemowej obsługi zapytań SSL. Należy jeszcze odpowiednio skonfigurowaćbroker za pomocą komendy mqsichangeproperties. Te operacje to: Włączenie obsługi SSL mqsichangeproperties [brokerName] -b httplistener -o HTTPListener -n enableSSLConnector -v true Ustawienie pliku z bazą certyfikatówmqsichangeproperties [brokerName] -b httplistener -o HTTPSConnector -n keystoreFile -v [fully qualified file path to keystore file] Ustawienie hasła do pliku z bazą certyfikatów mqsichangeproperties [brokerName] -b httplistener -o HTTPSConnector -n keystorePass -v [password for keystore] Ustawienie portu, na którym nasłuchuje broker na połączenia SSL mqsichangeproperties [brokerName] -b httplistener -o HTTPSConnector -n port -v [Port to listen on for https] Aby móc komunikować się za pomocą SSL z brokera będąc klientem (HTTPRequest) należy najpierw skonfigurować bazę certyfikatów, tzn. określić jakim certyfikatem broker będzie się przedstawiał oraz jakie certyfikaty są dla niego wiarygodne w tego typu komunikacji (od brokera). Standardowa baza certyfikatów znajduje się w pliku %MQSI_FILEPATH%\jre\lib\security\cacert. Jest to baza w formacie JKS i można ją zarządzać za pomocą standardowego narzędzia JAVA keytool lub z narzędzia okienkowego.Początkowe hasło do tego pliku to changeit i jak sama nazwa wskazuje należy ja jak najszybciej zmienić. Parametry noda HTTPRequest dotyczące połączenia szyfrowanego znajdują się w zakładce SSL.Znajduje się tam parametr Protocal. Przyjmuje on następujące wartości: SSL : Używa protokołu SSLv3, a jeśli się nie uda SSLv2 SSLv3 : Używa tylko protokołu SSLv3 TLS : Używa tylko protokołu TLS Kolejny parametr Allowed SSL Ciphersokreśla sposób kodowania podczas połączenia szyfrowanego. Jeśli tej wartości nie wprowadzimy broker przyjmie wartość domyślną, tj. wszystkie możliwe sposoby akceptowane przez JVM brokera. Dalej należy tylko i wyłącznie w polu Web Service URL podać odpowiedni adres URL zasobu wymagającego szyfrowanej komunikacji (prefix adresu https://). W tym miejscu postaram się przedstawić kilka przykładów manipulacji danymi komunikatu. Wyobraźmy sobie sytuacje, że w wejściowym komunikacie mamy dane CDATA, które będziemy chcieli w przepływiesparsować za pomocą odpowiedniego parsera, tak aby odczytać to pole nie jako łańcuch tekstowy, ale jako drzewo XML.Mamy wejściowy XML o poniższej strukturze, gdzie mamy tagi MESSAGE/A, a w nim wartość CDATA zawierający dynamicznąstrukturę XML. <?xml version="1.0" encoding="UTF-8"?> ... Wyobraźmy sobie wejściowy komunikat XML opakowany poprzez SOAP. <?xml version="1.0" ?> DECLARE cursor REFERENCE TO InputRoot.XMLNS; <message> Referencje ESQL to po części odpowiednik wskaźników języka C.Podczas deklaracji informujemy, że dany referencja wskazuje na konkretne miejsce w strukturze drzewa komunikatu. DECLARE myRef REFERENCE TO InputBody.Data.Invoice; W przypadku bardzo szczegółowego badania zachowania brokera można włączyć trace.Trace brokera dzielimy na systemowy (bardziej szczegółowy) i użytkownika. Dodatkowo możemy określić poziom logowania. Trace możemy określić na poziomie całej EG, jak również konkretnego przepływu. Aby włączyć trace należy użyć komendy mqsichangetrace. Pierwszym argumentem komendy jest nazwa brokera. Kolejne to odpowiednie przełączniki. Ciekawsze z nich to: -u lub -t : określa, czy włączany trace użytkownika, czy systemowy -e : określa nazwę Execution Group -f : określa nazwę przepływu, jeśli chcemy włączyć trace tylko konkretnego przepływu, a nie całego EG -l : określa poziom logowania (none, normal, debug) -r : usuwa całą informację o zarejestrowanych informacjach trace Następną operacją, jaką należy wykonać jest odczytanie informacji trace i zapisanie ich do pliku.Aby tego dokonać należy użyć komendy mqsireadlog. Pierwszym argumentem komendy jest nazwa brokera. Kolejne to odpowiednie przełączniki. Ciekawsze z nich to: -u lub -t : określa, czy włączany trace użytkownika, czy systemowy -e : określa nazwę Execution Group -o : nazwa pliku, do którego zostaną zapisane informacje trace Następnie jeśli chcemy przeanalizować te logi należy je przekonwertować do bardziej ludzkiej postaci.Aby tego dokonać należy użyć komendy mqsiformatlog. Argumenty tej komendy to: -i : nazwa pliku wejściowego z surowymi danymi trace -o : nazwa pliku, do którego zostaną zapisane sformatowane informacje trace Poniżej przedstawiona jest sekwencja przykładowych operacji jakie należy wykonać aby zgrać trace użytkownika do pliku. #włączenie trace dla przepływu Flow1 z jednoczesnym wykasowaniem starszych logów W czasie programowaia i projektowania pzepływów brokera często pojawia się konieczność sparametryzowania go.Chodzi tu o to aby np. w kodzie ESQL nie wpisywać na stałe wartości zmiennyh, tylko aby moc je definiować podczasdeploymentu. Takie parametry definiuje się na przepływie na zakładce User Defined Properties. Tam wprowadzamy nazwy i wartości parametrów. Aby użyć takiej zmiennej UDP w kodzie ESQL należy zadeklarować zmienną o identycznej nazwie z klauzlą EXTERNAL DECLARE username EXTERNAL CHARACTER ; W takiej sytuacji pod zmienną usename wprowadzana jest wartość zmiennej UDP o nazwie username. Aby użyć takiej zmiennej UDP w kodzie JAVA należy wywołać metodę getUserDefinedAttributez argumentem będącym nazwą zmiennej UDP. String username=(String)getUserDefinedAttribute("username"); Nody typu Timeout są nowego rodzaju nodami typu input.Pozwalają one na zainicjowanie przepływu nie poprzez pojawienie się komunikatu w kolejce, pojawienie się żądania HTTP, czy innych standardowych nodów typu input.Nody typu Timeout pozwalają na zainicjowanie przepływu na zasadzie schedulera.W najprostszym przypadku przeplyw jest inicjowany zaraz po uruchomieniu przepływu i następnie co określony na nodzie TimeoutNotification interwał czasowy. Jest to nod, który przyjmuje wejściowy komunikat np. wygenerowany ręcznie w nodzie Compute, dokonuje walidacji struktury komunikatu a następnie zapisuje odpowiedni komunikat w kolejce SYSTEM.BROKER.TIMEOUT.QUEUE. Taki utworzony komunikat TimeoutRequest ma postać: <TimeoutRequest> gdzie: Action Określa, czy notyfikacja jest tworzona, czy usuwana. IgnoreMissed Określa, czy notyfikacje Timeout, które powinny zostać wygenerowane, kiedy przepływ jest zatrzymany powinny zostać zignoowane (TRUE), czy też wywołane w momencie ponownego uruchomienia przepływu (FALSE). AllowOverwrite Określa, czy ponowne wywołanie komunikatu TimeoutRequest o tym samym identyfikatorze ma nadpisać już istniejący (TRUE), czy też jest to niemoziwei w takeij sytuacji zostanie wygenerowany błąd (FALSE). Tego typu nod pozwala na wygenerowanie komunikatu typu timeout LocalEnvironment W przypadku modułów ESQL istnieje możliwość wywołania metod JAVA prosto z kodu ESQL.Funkcjonalność polega na tym, że poza projektem z przepływami tworzymy projekt JAVA, który wskazujemy jako referencje w projekcie z przepływem. W efekcie w pliku bar poza przepływem deployuje się plik jar powstały z projektu JAVA i zawierający kod, który chcemy z ESQL wywołać. Następnie wewnątrz ESQL deklarujemy zewnętrzną procedurę JAVA, której parametry wejściowe i parametr wyjściowy odpowiadają parametrom kodu Java. Ważne jest, że metoda JAVA, która chcemy wywołać z kodu ESQL musi być typu static. Przykład procedury ESQL: CREATE PROCEDURE getRecords (IN cursor REFERENCE, IN queue_in CHARACTER ,IN host CHARACTER, IN port INTEGER, IN database CHARACTER, IN user CHARACTER, IN password CHARACTER) public static Boolean getRecords(MbElement tab, String queue_in Poniższa lista zawiera mapowanie typów danych pomiędzy ESQL a JAVA
Poniższa lista zawiera możliwe do odczytania z kodu ESQL lub JAVA parametry brokera.
Poniższa lista zawiera możliwe do odczytania z kodu ESQL lub JAVA parametry przepływu.
Poniższy przykład pokazuje w jaki sposób pobrać nazwę brokera z kodu ESQL. ... Poniższy przykład pokazuje w jaki sposób pobrać nazwę brokera z kodu JAVA. String brokerName =getBroker().getName(); Bardzo często się zdarza tak, że pewne parametry pliku bar są muszą być modyfikowane.Dzieje się tak na przykład przy uruchamianiu przepływu na różnych środowiskach.Kiedy mamy poza środowiskiem produkcyjnym środowisko deweloperskie, testowe to przed wdrożeniem pliku barmusimy niektóre jego parametry zmienić. Takim parametrem może być np. adres URL nodów HTTP. Mamy wtedy dwie możliwości. Pierwszą możliwością jest ręczna modyfikacja pliku bar przed jego wdrożeniem.Może to być jednak bardzo uciążliwe, w szczególności, kiedy tych parametrów będzie większa ilość. Drugi minus takiego rozwiązania jest fakt, ze zawsze przy ręcznych modyfikacjach jest większe prawdopodobieństwo popełnienia błędu. Innym sposobem jest użycie komendy toolkita (od wersji 6.0.2)mqsiapplybaroverride.Komenda przyjmuje następujące parametry: -b : położenie pliku bar -p : plik z parametrami do podmienienia W pliku bar, który jest zwykłych archiwum danych interesuje nas plik /META-INF/broker.xml. Plik ten zawiera m. in. parametry pliku bar. Aby móc modyfikować jakieś parametry pliku bar najlepiej nadać w naszym oryginalnym pliku wartości parametrów poprzez odpowiedni klucz. Dla przykładu jeśli mamy parametr wskazujący na pole URL noda HTTPRequest, to jako wartość nie podajemy konkretny adres URL, a np. {MYAPP_URL}.Kiedy otworzymy teraz plik bar i w nim /META-INF/broker.xmlto zobaczymy w nim wpis podobny do poniższego: <ConfigurableProperty override="{MYAPP_URL}" uri="HTTP_ILServices_Client1#HTTP_ILServices.URL"/> Teraz musimy dla każdego środowiska przygotować odpowiednie pliki properties zawierające docelowe wartościtego klucza oraz innych.Taki plik może mieć postać:{MYAPP_URL}=http://serverdev.com.pl/services/myservice Zadaniem komendymqsiapplybaroverridejest modyfikacja pliku bar a konkretnie w nim pliku /META-INF/broker.xmltak, aby zastąpić wszelkie wystąpienia kluczy na ich wartości z pliku properties.Wywołanie takiej komendy może mieć postać:mqsiapplybaroverride -b MK_DEPLOY.bar -p parameters.properties Przy developmencie przepływów, a następnie wdrażaniu ich na poszczególne środowiska ważne jest, aby wiedzieć dokładnie jaką wersje konkretnego przepływu mamy zainstalowaną. Mam tu na myśli wersje przepływu, kodu ESQL, Message Set, kodu JAVA oraz plików XSD.Oczywiście można ustawiać wszystkie informacje o wersji ręcznie, lecz ma to same wady.Jeśli robimy coś ręcznie zawsze istnieje możliwość, że popełnimy błąd. Dodatkowo jest to pracochłonne.Jeśli używamy jakiegoś systemu zarządzania wersją kodu wskazane jest aby informacja o wersji automatycznie propagowała się na parametr Version, jaki możemy przeczytać np. w opisie przepływu lub Message Set zainstalowanych na brokerze. W tym miejscy postaram się opisać konfiguracje takiego rozwiązania z wykorzystaniem CVS jako narzędzia do zarządzania wersją. W przypadku używania CVS ważne jest aby plik, w jakim automatycznie będą pojawiały się informacje o wersji były typu -kkv W rezultacie informacja o wersji danego obiektu pojawia sie jako parametr obiektu (przepływu, Message Set) zainstalowanego na brokerze. Każdy przepływ ma parametr Version. Aby pole to CVS automatycznie uzupełniał wersją przepływu należy wtym polu wprowadzić wartość$Revision: $. Analogiczny parametr istnieje dla Message Set. Jeśli plik zapisany w CVS jest typu -kkv, to powyższytekst jest uzupełniany przez numer wersji CVS. Aby nie ustawiać za każdym razem pola Version należy w konfiguracji toolkita przejść do menu Preferences, a następnie do zakładki Broker Development i Message Flow Editor i tam w polu Default Version Tag wpisać $Revision: $ Będzie to skutkowało tym, że każdy nowoutworzony przepływ będzie miał na tą wartość ustawione pole Version.Analogicznie robimy to dla Message Set. W przypadku kody ESQL najbardziej odpowiednim sposobem jego wersjonowania jest wprowadzenie do kodu wartości $Revision: $ jako komentarza. Innym ciekawym dodatkowym sposobem opisywania zasobów na brokerze jest używanie kluczy.Klucze pozwalają nam opisywać przepływy, czy też Message Set nie tylko przez numer wersji, ale przez dodatkowe informacje. Taką dodatkową informacją może być autor, opis, lub każda inna informacja.Następnie ta informacja pojawi się jako dodatkowe pole opisujące zdeployowany obiekt brokera. Takie dodatkowe informacje można umieszczać w polu Long Description przepływu, polu Label noda Passthrought lub jako komentarz w module ESQL. Format takiej informacji ma postać:$MQSI klucz = wartość MQSI$Dla przykładu jeśli chcemy umieścić informacje o autorze może to wyglądać następująco:$MQSI Autor = Marcin Kasiński MQSI$ Accounting and Statistics to technologia pozwalająca na zbieranie informacji statystycznych na temat działaniaprzepływów zainstalowanych na brokerze. Rozróżniamy dwa sposoby zbierania danych. Pierwszy to statystyki Snapshot zbierane co około 20 sekund.Zazwyczaj używa się ich do analizy konkretnych problemów wydajnościowych. Drugi to statystyki Archive używane zazwyczaj do długotrwałego monitorowania pracy brokera. Częstotliwość zbierania danych typu Archive określamyw minutach poprzez komendę mqsichangebroker. Zebrane dane mogą być zapisywane jako trace typu użytkownika i odczytywane jak standardowe informacje trace lub publikacje na odpowiedni topic. Przykład ustawienia tego interwału dla brokera WBRK_BROKERna 10 minut wygląda następująco: mqsichangebroker WBRK_BROKER -v 10 Włączenie i wyłączenie statystyk dokonujemy komendą mqsichangeflowstats. Sprawdzenie poziomu mitorowania dokonujemy komendąmqsireportflowstats Pierwszym argumentem komendy mqsichangeflowstatsjest nazwa brokera. kolejne to odpowiednie przełączniki: -a : komenda dotyczy danych typu Archive lub -s : komenda dotyczy danych typu Snapshot -e : nazwa execution group lub -g : komenda dotyczy wszystkich execution group -f : nazwa przepływu lub -j : komenda dotyczy wszystkich przepływów -c : włącza (wartość active) lub wyłącza (wartość inactive) monitorowanie -t : ustawia poziom logowania dla wątków (wartość none lub basic) -n : ustawia poziom logowania dla nodów (wartość none, basic lub advanced) -r : czyści poprzednie wpisy -o : ustawia docelowe położenie statystyk (wartość usertrace, xml lub smf dla zOS) -b : parametr służący do filtrowania statystyk według pola accountingOrigin. Poniżej kilka przykładów użycia komendymqsichangeflowstats. Włącznie monitorowania typu Archive mqsichangeflowstats WBRK_BROKER -a -g -j -c active -t basic -r -o usertrace Wyłącznie monitorowania typu Archive mqsichangeflowstats WBRK_BROKER -a -g -j -c inactive -t basic -r -o usertrace Sprawdzenie poziomu monitorowania typu Archive mqsireportflowstats WBRK_BROKER -a -g -j Włącznie monitorowania typu Snapshot mqsichangeflowstats WBRK_BROKER -s -g -j -c active -t basic -o usertrace Wyłącznie monitorowania typu Snapshot mqsichangeflowstats WBRK_BROKER -s -g -j -c inactive -t basic -o usertrace Sprawdzenie poziomu monitorowania typu Snapshot mqsireportflowstats WBRK_BROKER -s -g -j Aby dynamicznie określić "domenę" statystyk, według której później będziemy mogli filtrować statystykimożemy użyć poniższego kodu ESQL. SET Environment.Broker.Accounting.Origin = "CustomerXY"; Poniższa lista przedstawia ogólne dane statystyczne znajdujące się w folderze WMQIStatisticsAccounting.
Poniższa lista przedstawia dane statystyczne dotyczące przepływów znajdujące się w folderze MessageFlow.
Poniższa lista przedstawia dane statystyczne dotyczące wątków znajdujące się w folderze Threads.
Poniższa lista przedstawia dane statystyczne dotyczące konkretnych wątków znajdujące się w podfolderze ThreadStatisticsfolderuThreads.
Poniższa lista przedstawia dane statystyczne dotyczące nodów znajdujące się w folderze Nodes.
Poniższa lista przedstawia dane statystyczne dotyczące konkretnych nodów znajdujące się w podfolderze NodesStatisticsfolderuNodes.
Poniższa lista przedstawia dane statystyczne dotyczące terminali znajdujące się w folderze TerminalStatistics.
Wyświetlanie listy brokerów private static void displayBrokerNames(ConfigManagerProxy cmp) private static void deleteBroker(ConfigManagerProxy cmp, String brokerName) { private static void displayBrokerEGs(ConfigManagerProxy cmp, private static void displayACLs(ConfigManagerProxy cmp) private static void createACL(ConfigManagerProxy cmp, String user) { private static void displaySubs(ConfigManagerProxy cmp) throws Exception "WebSphere Message Broker - Message Flows" : IBM "WebSphere Message Broker - ESQL" : IBM "WebSphere Message Broker - Configuration, Administration, and Security" : IBM "WebSphere Message Broker" : IBM Info Center |
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||