簡體   English   中英

如何知道何時失去與JMS主題的連接?

[英]How to know when connection to a JMS Topic is lost?

我有一個Java富客戶端應用程序,它在啟動時在遠程HornetQ JMS主題上注冊了持久訂閱。 但是,如果服務器重新啟動,則連接將丟失,並且只能通過重新啟動客戶端應用程序來恢復。 這會導致混亂的情況,即沒有收到JMS消息,並且在客戶端重新啟動后立即收到很多消息。

一種簡單的恢復連接的解決方案是運行計時器以定期檢查連接是否仍然有效,否則嘗試重新連接。 或者,如果在一定時間后仍未收到心跳,則服務器可以向客戶端發送心跳,並嘗試重新連接(如此答案中所述 )。

但是,這兩種方法似乎都很難解決這個問題,因此,我想知道是否有更好的解決方案來確定該連接不再可用?

要獲得斷開連接的通知,必須在啟動連接之前在TopicConnection上注冊ExceptionListener

private void subscribe() throws JMSException {

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

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

ExceptionListener您可以檢查收到的JMSException的錯誤代碼。 (錯誤代碼是特定於供應商的)
對於HornetQ,連接DISCONNECT會收到錯誤代碼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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM