2016-03-02 8 views
0

У меня есть клиентское приложение, богатое Java, которое регистрирует долговременную подписку на удаленную тему HornetQ JMS при запуске. Однако, если сервер перезагружается, соединение теряется и может быть восстановлено только путем перезапуска клиентского приложения. Это приводит к запутывающим ситуациям, когда сообщения JMS не принимаются и после того, как клиент перезагружает много сообщений, принимаются сразу.Как узнать, когда соединение с темой JMS потеряно?

Простым решением для восстановления соединения было бы запустить таймер, чтобы периодически проверять, действительно ли соединение по-прежнему действует и попытаться повторно подключиться. В качестве альтернативы сервер может послать пульс клиенту и попытаться подключиться, если после определенного периода времени не будет приниматься пульс (как указано в этом answer).

Но оба кажутся неуклюжими подходами к этой проблеме, и поэтому я хотел бы знать, есть ли лучшее решение, чтобы узнать, что соединение больше не доступно?

ответ

0

Чтобы получить уведомление об отключении, вы должны зарегистрировать ExceptionListener на своем TopicConnection, прежде чем приступить к подключению.

private void subscribe() throws JMSException { 

    // get context/create connection and session/etc. 
    TopicConnection connection = ... 

    connection.setExceptionListener(this::handleExceptions); 
    connection.start(); 
} 

В ExceptionListener вы можете проверить код ошибки принятого JMSException. (Коды ошибок зависят от поставщика)
В случае HornetQ код ошибки DISCONNECT принимается после потери соединения.

private static final String HORNETQ_DISCONNECT_ERROR_CODE = "DISCONNECT"; 

private void handleExceptions(final JMSException jmsException) { 

    final String errorCode = jmsException.getErrorCode(); 
    if (HORNETQ_DISCONNECT_ERROR_CODE.equals(errorCode)) { 
     tryConnect(); 
    } 
} 

Затем вы можете запустить самоотверждающийся таймер, который пытается повторно подключить каждые x секунд до тех пор, пока он не удастся.

private static final long SUBSCRIBE_RETRY_TIME_OUT_IN_MILLIS = 60000; 

private void tryConnect() { 

    final Timer timer = new Timer("JMS-Topic-Reconnection-Timer", true); 
    final TimerTask timerTask = new TimerTask() { 

     @Override 
     public void run() { 
      try { 
       subscribe(); 
       // cancel the timer, after the subscription succeeds 
       timer.cancel(); 
      } 
      catch (final Exception e) { 
       logger.info("reconnect to jms topic failed: {}", e.getMessage()); 
      } 
     } 
    }; 
    timer.schedule(timerTask, SUBSCRIBE_RETRY_TIME_OUT_IN_MILLIS, SUBSCRIBE_RETRY_TIME_OUT_IN_MILLIS); 
}