简体   繁体   English

如何知道何时失去与JMS主题的连接?

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

I have a Java rich client application that registers a durable subscription on a remote HornetQ JMS Topic on startup. 我有一个Java富客户端应用程序,它在启动时在远程HornetQ JMS主题上注册了持久订阅。 However if the server restarts the connection is lost and can only be restored by restarting the client application. 但是,如果服务器重新启动,则连接将丢失,并且只能通过重新启动客户端应用程序来恢复。 This leads to confusing situations where JMS messages are not received and after a client restart a lot of messages are received at once. 这会导致混乱的情况,即没有收到JMS消息,并且在客户端重新启动后立即收到很多消息。

A simple solution to restore connection would be to run a timer to periodically check if the connection is still valid and try to reconnect otherwise. 一种简单的恢复连接的解决方案是运行计时器以定期检查连接是否仍然有效,否则尝试重新连接。 Alternatively the server could send a heartbeat to the client and try to reconnect if no heartbeat is received after a certain period (like mentioned in this answer ). 或者,如果在一定时间后仍未收到心跳,则服务器可以向客户端发送心跳,并尝试重新连接(如此答案中所述 )。

But both seem like clumsy approaches to this problem and therefore I would like to know if there is a better solution to find out that the connection is not available anymore? 但是,这两种方法似乎都很难解决这个问题,因此,我想知道是否有更好的解决方案来确定该连接不再可用?

To get notified on the disconnection you have to register an ExceptionListener on your TopicConnection before you start the connection. 要获得断开连接的通知,必须在启动连接之前在TopicConnection上注册ExceptionListener

private void subscribe() throws JMSException {

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

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

In the ExceptionListener you can check the error code of the received JMSException . ExceptionListener您可以检查收到的JMSException的错误代码。 (The error codes are vendor-specific) (错误代码是特定于供应商的)
In the case of HornetQ the error code DISCONNECT is received after the connection is lost. 对于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();
    }
}

Then you can start a self-canceling Timer that tries to reconnect every x seconds until it succeeds. 然后,您可以启动一个自取消计时器,该计时器尝试每隔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