2010-07-06 3 views
16

В JMS легко узнать, потеряно ли соединение, исключение происходит. Но как узнать, снова ли соединение?Как узнать, есть ли соединение JMS?

Сценарий: Я использую JMS для связи с моим сервером. Теперь мое соединение прерывается (сервер отключен), что приводит к исключению. Все идет нормально. Если сервер снова запущен и соединение восстановлено, откуда я это знаю?

Я не вижу слушателей, которые облегчили бы такую ​​информацию.

ответ

15

Ahhh ... старая обработка исключений/пересоединение.

Есть некоторые поставщики транспорта, которые автоматически подключат ваше приложение к вам и к тем, кто заново подключит приложение. В общем случае пересоединения скрывают исключение из приложения. Нижняя сторона заключается в том, что вы не хотите, чтобы приложение зависало вечно, если все удаленные узлы обмена сообщениями так опущены, что в конечном счете вы должны включать некоторую логику пересоединения.

Теперь вот интересная часть - как вы обрабатываете исключения в нейтральном режиме провайдера? Исключение JMS практически бесполезно. Например, «исключение безопасности» может быть в том, что политики безопасности Java слишком ограничены, что разрешения файловой системы слишком ограничены, что учетные данные LDAP не удались, что соединение с транспортом завершилось неудачно, что открытие очереди или темы не удалось или какой-либо из десятков других проблем, связанных с безопасностью. Это связанное исключение, в котором есть данные от поставщика транспорта, которые действительно помогают отладить проблему. Мои клиенты обычно использовали один из трех разных подходов здесь:

  1. Рассматривайте все ошибки одинаково. Закройте все объекты и повторите их инициализацию. это JMS portable.
  2. Разрешить приложению проверять связанные исключения, чтобы различать фатальные и временные ошибки (то есть ошибка аутентификации по сравнению с полной очередью). Не поставщик портативный.
  3. Специфичные для поставщика классы обработки ошибок. Гибрид двух других.

В вашем случае объекты очереди и темы, вероятно, действительны только в контексте исходного соединения. Предполагая, что провайдер, который автоматически подключится к тому факту, что вы получили исключение, означает, что пересоздание завершилось неудачно, и контекст для объектов очереди и темы не удалось восстановить. Закройте все объекты и снова подключите их.

Если вы хотите сделать что-то более специфичное для провайдера, например, различать переходные и постоянные ошибки, это одно из тех, «зависящих» от вещей, и вам придется разобраться с этим в каждом конкретном случае.

+0

Дело в том, что если у меня есть, скажем, клиент GUI, который обменивается данными через JMS с сервером, просто не имеет смысла заливать очередь сообщениями, которые нельзя обрабатывать в любом случае, потому что сервер не работает. Поэтому я предполагаю, что единственным реалистичным вариантом было бы отправить «ping» с интервалом (с низким ttl), чтобы проверить, возможно ли (или снова) общаться с сервером. Это подход, который вы бы рекомендовали? – Mauli

+0

Это общий подход. Например, WebSphere MQ Explorer будет обновлять свое подключение к диспетчеру очереди каждые 15 секунд по умолчанию. Если вызов API завершается неудачно, в клиенте запускается пересоединение. Если это сработает, GUI просто займет дополнительную секунду, чтобы ответить. Если это не удается, GUI получает исключение и управляет своей собственной логикой повторного подключения. В случае приложений я обычно советую людям проектировать вызовы инструментальных средств в их API, например, не-транзакционный «пинг» именно по этой причине. –

4

Спецификация JMS не описывает какой-либо транспортный протокол, он ничего не говорит о соединениях (т. Е. Если брокер сохраняет их в живых или устанавливает новое соединение для каждой сессии). Итак, я думаю, что вы подразумеваете под

Теперь мое соединение прерывается (сервер опущен), что приводит к исключению.

является то, что вы пытаетесь отправить сообщение, и вы получаете исключение JmsException.

Я думаю, единственный способ узнать, есть ли брокер, это попытаться отправить сообщение.

+1

Точно - потому, что JMS является асинхронной протокол, реализация может иметь соединения, установленные скоротечно - только потому, что подключения удалось Безразлично 't означает, что очередь теперь доступна. –

1

Ваш единственный вариант в случае JMSException, основанного на подключении, заключается в попытке восстановить соединение в вашем обработчике исключений и повторить операцию.

5

Лучший способ следить за исключением соединения устанавливает прослушиватель исключения, например:

ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("jmsContextName"); 
     connection = connectionFactory.createConnection(); 
     connection.setExceptionListener(new ExceptionListener() { 
      @Override 
      public void onException(JMSException exception) { 
       logger.error("ExceptionListener triggered: " + exception.getMessage(), exception); 
       try { 
        Thread.sleep(5000); // Wait 5 seconds (JMS server restarted?) 
        restartJSMConnection(); 
       } catch (InterruptedException e) { 
        logger.error("Error pausing thread" + e.getMessage()); 
       } 
      } 
     }); 
     connection.start(); 
Смежные вопросы