【问题标题】:Spring ActiveMQ Connection Error Handling in a Loop循环中的 Spring ActiveMQ 连接错误处理
【发布时间】:2017-06-29 06:36:03
【问题描述】:

我的应用程序的一部分需要一个恒定循环来检查我们的 ActiveMQ 消息队列是否“工作”。我已经使用在 Spring 初始化所有内容后启动的专用线程进行了设置,因此我拥有了我需要的所有 DI 项目。该线程现在处理 while(true) 循环中的所有内容,以便继续查找消息。

我正在设置一个 ActiveMQConnectionFactory 并注入它。使用该 AMQCF,在循环中我创建一个新的Connection,从连接中设置一个Session,设置一个Destination,最后查看MessageConsumerreceive(5000)。如果检测到消息,我会处理它,一切都很好。

我的问题是我的应用程序和代理之间的连接问题。如果连接中断(AMQ 出现故障等),则会引发异常,一切都会崩溃。

javax.jms.JMSException: java.io.EOFException
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:72)
at org.apache.activemq.ActiveMQMessageConsumer.dequeue(ActiveMQMessageConsumer.java:492)
at org.apache.activemq.ActiveMQMessageConsumer.receive(ActiveMQMessageConsumer.java:650)
at [AMQThreadClass]
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:268)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:240)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:232)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:215)
... 1 more

设置连接工厂时,我使用包含故障转移jms.location=failover:(tcp://localhost:61616)?reconnectDelayExponent=2.0&useExponentialBackOff=true&initialReconnectDelay=30&maxReconnectAttempts=0 的位置,我认为该位置可以工作。我认为可能还缺少其他一些东西,无论是循环还是我如何处理连接/会话/目标/消费者循环的想法。

有谁知道安全处理必然发生的连接问题的正确方法是什么?

【问题讨论】:

  • 我没有使用过 ActiveMQ,所以我无法帮助你,但是当你说你的代码中有 while(true) 时,我真的很害怕。如果一个 spring bean 需要启动线程,连接到套接字,那么你可能应该实现 SmartLifecyle,spring 会在上下文刷新和关闭时自动调用 start 和 stop。通常你有一个private volatile boolean shutdown,你在线程成功启动后设置为true,停止你设置shutdown=false,在你的线程内你有while(!shuitown)
  • @KlausGroenbaek 我见过很多while(!shutdown) 样式循环来处理退出。那是接下来要做的事情:) 一步一步。感谢SmartLifecycle 的建议,我会定义的。检查一下。

标签: java spring jms activemq


【解决方案1】:

在 URI 中包含重新连接字符串似乎很有帮助。这有助于尝试保持连接活跃。我最终在 Spring 中使用了 DefaultMessageListenerContainerMessageListenerAdapter 以及 TaskExecutor 来处理队列的“监视”。这使得它可以使用 Spring 进行监控,并且不需要更高的线程来处理队列上的循环。

一个必要的步骤是确保将其设置为autoStartup(false)。如果在 Spring 尝试初始化 Bean 时队列已关闭,它将一直等待并且永远不会启动。为了处理启动连接(启动监控集),我为 Spring 添加了一个 implements ApplicationListener<ContextRefreshedEvent> 的 Startup Housekeeper 类型的线程。这样在应用程序启动时,在 Bean 初始化并且一切都“稳定”之后,我可以尝试调用 ListenerContainer 来启动。

启动容器已移至其自己的线程中,因此它可以从应用程序异步完成,并且在连接未准备好时不会阻塞。这允许应用程序正常启动(排队或排队),然后在可能的情况下连接,添加侦听器来处理传入的任何消息。

不需要讨厌的while循环:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-05
    • 2023-03-26
    • 2011-11-30
    • 1970-01-01
    • 2015-08-26
    • 2019-09-24
    • 2015-02-07
    • 1970-01-01
    相关资源
    最近更新 更多