【发布时间】:2011-03-12 09:41:57
【问题描述】:
在 JMS 中很容易发现连接是否丢失,是否发生异常。但是如何确定连接是否再次存在?
场景:我使用 JMS 与我的服务器通信。现在我的连接中断(服务器已关闭),导致异常。到目前为止,一切都很好。如果服务器再次启动并重新建立连接,我怎么知道?
我没有看到任何有助于提供此类信息的侦听器。
【问题讨论】:
在 JMS 中很容易发现连接是否丢失,是否发生异常。但是如何确定连接是否再次存在?
场景:我使用 JMS 与我的服务器通信。现在我的连接中断(服务器已关闭),导致异常。到目前为止,一切都很好。如果服务器再次启动并重新建立连接,我怎么知道?
我没有看到任何有助于提供此类信息的侦听器。
【问题讨论】:
JMS 规范没有描述任何传输协议,它没有说明任何关于连接的内容(即代理应该保持它们处于活动状态还是为每个会话建立一个新连接)。所以,我认为你的意思是
现在我的连接中断(服务器已关闭),导致异常。
是您尝试发送消息并且收到 JmsException。
我认为,查看代理是否启动的唯一方法是尝试发送消息。
【讨论】:
对于基于连接的 JMSException,您唯一的选择是尝试在异常处理程序中重新建立连接,然后重试该操作。
【讨论】:
啊……旧的异常处理/重新连接难题。
有些传输提供商会自动为您重新连接您的应用程序,而有些则让应用程序驱动重新连接。通常,重新连接会对应用程序隐藏异常。不利的一面是,如果所有远程消息传递节点都关闭,您不希望应用程序永远挂起,因此最终,您必须包含一些重新连接逻辑。
现在是有趣的部分 - 您如何以提供者中立的方式处理异常? JMS 异常实际上毫无价值。例如,“安全异常”可能是 Java 安全策略过于严格、文件系统权限过于严格、LDAP 凭证失败、与传输的连接失败、队列或主题的打开失败或许多其他与安全相关的问题中的任何一个。链接异常具有来自传输提供商的详细信息,真正有助于调试问题。我的客户通常在这里采用三种不同方法中的一种...
在您的情况下,队列和主题对象可能仅在原始连接的上下文中有效。假设提供者自动重新连接,您遇到异常意味着重新连接失败,并且无法恢复队列和主题对象的上下文。关闭所有对象并重新连接。
您是否想做一些更特定于提供商的事情,例如区分暂时性和永久性错误是“取决于”的事情之一,您必须根据具体情况来解决。
【讨论】:
监控连接异常的最佳方式是设置异常监听器,例如:
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(); 的外观如何?