【问题标题】:How to find out if JMS Connection is there?如何确定 JMS 连接是否存在?
【发布时间】:2011-03-12 09:41:57
【问题描述】:

在 JMS 中很容易发现连接是否丢失,是否发生异常。但是如何确定连接是否再次存在?

场景:我使用 JMS 与我的服务器通信。现在我的连接中断(服务器已关闭),导致异常。到目前为止,一切都很好。如果服务器再次启动并重新建立连接,我怎么知道?

我没有看到任何有助于提供此类信息的侦听器。

【问题讨论】:

    标签: java jms


    【解决方案1】:

    JMS 规范没有描述任何传输协议,它没有说明任何关于连接的内容(即代理应该保持它们处于活动状态还是为每个会话建立一个新连接)。所以,我认为你的意思是

    现在我的连接中断(服务器已关闭),导致异常。

    是您尝试发送消息并且收到 JmsException。

    我认为,查看代理是否启动的唯一方法是尝试发送消息。

    【讨论】:

    • 没错 - 因为 JMS 是一个异步协议,所以实现可以暂时建立连接 - 仅仅因为连接成功并不意味着队列现在仍然可用。
    【解决方案2】:

    对于基于连接的 JMSException,您唯一的选择是尝试在异常处理程序中重新建立连接,然后重试该操作。

    【讨论】:

      【解决方案3】:

      啊……旧的异常处理/重新连接难题。

      有些传输提供商会自动为您重新连接您的应用程序,而有些则让应用程序驱动重新连接。通常,重新连接会对应用程序隐藏异常。不利的一面是,如果所有远程消息传递节点都关闭,您不希望应用程序永远挂起,因此最终,您必须包含一些重新连接逻辑。

      现在是有趣的部分 - 您如何以提供者中立的方式处理异常? JMS 异常实际上毫无价值。例如,“安全异常”可能是 Java 安全策略过于严格、文件系统权限过于严格、LDAP 凭证失败、与传输的连接失败、队列或主题的打开失败或许多其他与安全相关的问题中的任何一个。链接异常具有来自传输提供商的详细信息,真正有助于调试问题。我的客户通常在这里采用三种不同方法中的一种...

      1. 对所有错误一视同仁。关闭所有对象并重新初始化它们。这是 JMS 可移植的。
      2. 允许应用检查链接的异常以区分致命错误和暂时错误(即身份验证错误与队列已满)。不是提供者可移植的。
      3. 提供者特定的错误处理类。其他两者的混合体。

      在您的情况下,队列和主题对象可能仅在原始连接的上下文中有效。假设提供者自动重新连接,您遇到异常意味着重新连接失败,并且无法恢复队列和主题对象的上下文。关闭所有对象并重新连接。

      您是否想做一些更特定于提供商的事情,例如区分暂时性和永久性错误是“取决于”的事情之一,您必须根据具体情况来解决。

      【讨论】:

      • 问题是,如果我有一个通过 JMS 与服务器通信的 GUI 客户端,那么用无论如何都无法处理的消息淹没队列是没有意义的,因为服务器已关闭。所以我想唯一现实的选择是每隔一段时间(低ttl)发送一个“ping”,以检查是否仍然可以(或再次)与服务器通信。这是您推荐的方法吗?
      • 这是一种常见的方法。例如,默认情况下,WebSphere MQ Explorer 将每 15 秒刷新一次与队列管理器的连接。如果 API 调用失败,则在客户端中驱动重新连接。如果这有效,GUI 只需多花一秒钟的时间来响应。如果失败,GUI 会收到异常并驱动自己的重新连接逻辑。对于应用程序,我通常建议人们在他们的 API 中设计检测调用,例如非事务性“ping”。
      【解决方案4】:

      监控连接异常的最佳方式是设置异常监听器,例如:

      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();
      

      【讨论】:

      • restartJSMConnection(); 的外观如何?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-13
      • 2017-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多