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