Irek Słonina

Irek Słonina programowanie, bazy
danych i linuksy

Temat: JMS MessageListener i zanik połączenia

Witam,

od pewnego czasu moja aplikacja z bliżej nieokreślonych przyczyn
o losowych porach przestaje odbierać komunikaty z EAI.
Podejrzewam zaniki połączenia sieciowego pomiędzy środowiskiem
aplikacji, a szyną EAI.
Przyczyna na chwilę obecną mniejszym problemem, większym jest
sposób reakcji aplikacji na awarię.

Aplikacja nie rzuca mi żadnym wyjątkiem, nie mam żadnego śladu
w logach dotyczącego awarii połączenia.
Nie mam dużego doświadczenia w JMS'ach więc proszę o poradę:
stosujecie jakieś watchdogi sprawdzające stan połączenia?
Może gdzieś nie łapię potrzebnego wyjątku albo trzeba zastosować
jakieś dodatkowe przełączniki w klasach połączeniowych?

Mam ograniczony dostęp do szyny, a tym bardziej symulację awarii
dlatego w pierwszej kolejności szukam błędów w kodzie.

Uproszczony kod, który stosuję do podłączenia się do szyny:


package TMP;

import com.ibm.jms.JMSTextMessage;
import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQQueueConnection;
import com.ibm.mq.jms.MQQueueConnectionFactory;
import com.ibm.mq.jms.MQQueueReceiver;
import com.ibm.mq.jms.MQQueueSession;
import java.util.Enumeration;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;

public class EAIListenerProto {

public EAIListenerProto() {
MQQueueConnection c;
MQQueueReceiver receiver = null;
MQQueueSession sessionIn;
try {
MQQueueConnectionFactory qcf = new MQQueueConnectionFactory();
// [tutaj wlasciwe ustawianie qcf, SSL itp.]
c = (MQQueueConnection) qcf.createConnection();
sessionIn = (MQQueueSession) c.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
MQQueue queueIn = (MQQueue) sessionIn.createQueue("queue:///JAKIS.IN");
receiver = (MQQueueReceiver) sessionIn.createReceiver(queueIn);
c = (MQQueueConnection) qcf.createConnection();

receiver.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
JMSTextMessage msg = null;

if (arg0 instanceof JMSTextMessage) {
try {
msg = (JMSTextMessage) arg0;
Enumeration en = arg0.getPropertyNames();
int i = 0;
while (en.hasMoreElements()) {
String x = en.nextElement().toString();
System.out.println("enum " + i + ": " + x);
System.out.println("val " + i + ": " + arg0.getObjectProperty(x));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
c.start();

} catch (Throwable ex) {
ex.printStackTrace();
}
}

}
Paweł Grzegorz Kwiatkowski

Paweł Grzegorz Kwiatkowski Architekt
oprogramowania,
Ericsson

Temat: JMS MessageListener i zanik połączenia

A co po drodze między aplikacją a szyną? Jakiś firewall?

Nie wyłapujesz innych typów wiadomości? Choćby logowanie, że coś innego przyszło ?
<code>
...
if (arg0 instanceof JMSTextMessage)
...
</code>

Jak rozumiem klauzule try/catch są w tej wersji kodu uproszczone i obsługa wyjątków jakoś wygląda?

pozdrawiam,
Paweł
Irek Słonina

Irek Słonina programowanie, bazy
danych i linuksy

Temat: JMS MessageListener i zanik połączenia

Paweł Grzegorz Kwiatkowski:
A co po drodze między aplikacją a szyną? Jakiś firewall?

Nie wiem tego, aplikacja działa w obcym środowisku.
Nie wyłapujesz innych typów wiadomości? Choćby logowanie, że coś innego przyszło ?

Wyłapuję, wydawało mi się że ten kawałek kodu nie jest istotny dla tego problemu.
Jak rozumiem klauzule try/catch są w tej wersji kodu uproszczone i obsługa wyjątków jakoś wygląda?

Oczywiście mam inaczej rozwiązaną obsługę wyjątków niż ex.printStackTrace() - ale wyłapywane wyjątki są takie jak w przytoczonym przykładzie.Irek Słonina edytował(a) ten post dnia 23.12.09 o godzinie 14:14
Paweł Grzegorz Kwiatkowski

Paweł Grzegorz Kwiatkowski Architekt
oprogramowania,
Ericsson

Temat: JMS MessageListener i zanik połączenia

Ciężko powiedzieć co może być przyczyną :) Co mi się jeszcze rzuca w oczy, to:

...
c.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
..


..ale nie widzę, żeby gdzieś było wołane acknowledge(). Być może to kwestia uproszczonego kodu.

konto usunięte

Temat: JMS MessageListener i zanik połączenia

Jeśli Twoja aplikacja przestaje odbierać połączenia (onMessage nie jest wywołany) to i tak nie masz pewności, że będziesz mieć jakiekolwiek symptomy błędu. Najwyraźniej, do Twojej aplikacji nie zostają dostarczane komunikaty. No i tak:

1. Komunikaty nie dostarczone do miejsca docelowego, trafiają do martwej kolejki (Death Queue). Być może, że w komunikatach masz wyjaśnienie błędu (jaki to serwer aplikacji i jaka platforma dla Websphere MQ ?). Musisz zaglądnąć do martwej kolejki.

2. Jest też kolejka z błędami systemowymi. Masz do niej dostęp ?

3. Jaki jest "backend store" ? System plików czy DB ? Jeśli ten pierwszy, to pytanie czy nie jest przepełniony.

Jeśli chodzi o zaniki połączenia, to pytanie jak jest skonfigurowana kolejka. Generalnie, w zastosowaniach produkcyjnych, kolejka powinna mieć ustawione atrybut gwarantowania dostarczenia komunikatu. Jeśli nawet byłyby problemy z zanikiem połączenia, to i tak komunikat przez N prób powinien być dostarczany. Jeśli nie zostanie dostarczony, patrz p.1
Irek Słonina:
Witam,

od pewnego czasu moja aplikacja z bliżej nieokreślonych przyczyn
o losowych porach przestaje odbierać komunikaty z EAI.
Podejrzewam zaniki połączenia sieciowego pomiędzy środowiskiem
aplikacji, a szyną EAI.
Przyczyna na chwilę obecną mniejszym problemem, większym jest
sposób reakcji aplikacji na awarię.

Aplikacja nie rzuca mi żadnym wyjątkiem, nie mam żadnego śladu
w logach dotyczącego awarii połączenia.
Nie mam dużego doświadczenia w JMS'ach więc proszę o poradę:
stosujecie jakieś watchdogi sprawdzające stan połączenia?
Może gdzieś nie łapię potrzebnego wyjątku albo trzeba zastosować
jakieś dodatkowe przełączniki w klasach połączeniowych?

Mam ograniczony dostęp do szyny, a tym bardziej symulację awarii
dlatego w pierwszej kolejności szukam błędów w kodzie.

Uproszczony kod, który stosuję do podłączenia się do szyny:


package TMP;

import com.ibm.jms.JMSTextMessage;
import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQQueueConnection;
import com.ibm.mq.jms.MQQueueConnectionFactory;
import com.ibm.mq.jms.MQQueueReceiver;
import com.ibm.mq.jms.MQQueueSession;
import java.util.Enumeration;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;

public class EAIListenerProto {

public EAIListenerProto() {
MQQueueConnection c;
MQQueueReceiver receiver = null;
MQQueueSession sessionIn;
try {
MQQueueConnectionFactory qcf = new MQQueueConnectionFactory();
// [tutaj wlasciwe ustawianie qcf, SSL itp.]
c = (MQQueueConnection) qcf.createConnection();
sessionIn = (MQQueueSession) c.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
MQQueue queueIn = (MQQueue) sessionIn.createQueue("queue:///JAKIS.IN");
receiver = (MQQueueReceiver) sessionIn.createReceiver(queueIn);
c = (MQQueueConnection) qcf.createConnection();

receiver.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
JMSTextMessage msg = null;

if (arg0 instanceof JMSTextMessage) {
try {
msg = (JMSTextMessage) arg0;
Enumeration en = arg0.getPropertyNames();
int i = 0;
while (en.hasMoreElements()) {
String x = en.nextElement().toString();
System.out.println("enum " + i + ": " + x);
System.out.println("val " + i + ": " + arg0.getObjectProperty(x));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
c.start();

} catch (Throwable ex) {
ex.printStackTrace();
}
}

}
Paweł Grotowski edytował(a) ten post dnia 23.12.09 o godzinie 22:00
Irek Słonina

Irek Słonina programowanie, bazy
danych i linuksy

Temat: JMS MessageListener i zanik połączenia

Paweł Grzegorz Kwiatkowski:
Ciężko powiedzieć co może być przyczyną :) Co mi się jeszcze rzuca w oczy, to:

...
c.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE);
..


..ale nie widzę, żeby gdzieś było wołane acknowledge(). Być może to kwestia uproszczonego kodu.

Upraszczając zepsułem podstawową funkcjonalność. Oczywiście commit()uję w odpowiednim momencie.
Irek Słonina

Irek Słonina programowanie, bazy
danych i linuksy

Temat: JMS MessageListener i zanik połączenia

Paweł Grotowski:
Jeśli Twoja aplikacja przestaje odbierać połączenia (onMessage nie jest wywołany) to i tak nie masz pewności, że będziesz mieć jakiekolwiek symptomy błędu. Najwyraźniej, do Twojej aplikacji nie zostają dostarczane komunikaty. No i tak:

1. Komunikaty nie dostarczone do miejsca docelowego, trafiają do martwej kolejki (Death Queue). Być może, że w komunikatach masz wyjaśnienie błędu (jaki to serwer aplikacji i jaka platforma dla Websphere MQ ?). Musisz zaglądnąć do martwej kolejki.

2. Jest też kolejka z błędami systemowymi. Masz do niej dostęp ?

3. Jaki jest "backend store" ? System plików czy DB ? Jeśli ten pierwszy, to pytanie czy nie jest przepełniony.

Nie wiem niestety nic na temat platformy. Nie mam też dostępu do kolejek.
Administracja EAI należy do zewnętrznej firmy. Dostałem informację, że w czasie gdy gubiłem połączenie połączenia przypadały prace inwentaryzacyjne, łącznie z restartowaniem całego środowiska obsługującego EAI itp.

Nie znaleziono również błędów, które mogłyby mi pomóc w rozwiązaniu problemu.
Jeśli chodzi o zaniki połączenia, to pytanie jak jest skonfigurowana kolejka. Generalnie, w zastosowaniach produkcyjnych, kolejka powinna mieć ustawione atrybut gwarantowania dostarczenia komunikatu. Jeśli nawet byłyby problemy z zanikiem połączenia, to i tak komunikat przez N prób powinien być dostarczany. Jeśli nie zostanie dostarczony, patrz p.1


Prawdopodobnie EAI zostało wyłączone na chwilę. Po wystartowaniu szyny potrzebuję od nowa nawiązać całą komunikację, łącznie z ponowną autentykacją.
Wygląda na to, że będę musiał odtworzyć tę sytuację w sposób kontrolowany i nauczyć aplikację odtwarzania połączenia, nawet po dłuższym wyłączeniu EAI.

Dzięki wam za pomoc.Irek Słonina edytował(a) ten post dnia 28.12.09 o godzinie 15:40
Irek Słonina

Irek Słonina programowanie, bazy
danych i linuksy

Temat: JMS MessageListener i zanik połączenia

Dla potomnych.
Aby wychwycić wyjątki dotyczące błędów połączenia z szyną należy ustawić dodatkowego ExceptionListenera na obiekcie MQQueueConnection.


MQQueueConnection c = (MQQueueConnection) qcf.createConnection();
c.setExceptionListener(new ExceptionListener() {
@Override
public void onException(JMSException arg0) {
arg0.printStackTrace();
}
});

Następna dyskusja:

problem z JMS




Wyślij zaproszenie do