2017-02-10 136 views
0

我的应用程序的一部分需要一个恒定的循环来检查我们的ActiveMQ消息队列中的“工作”。我已经使用专门的线程设置了这个,在Spring初始化所有东西之后开始,所以我拥有了我需要的所有DI项。该线程现在处理while(true)循环中的所有内容,只是继续查找消息。Spring中的ActiveMQ连接错误处理

我正在设置一个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我本以为这工作的位置。我认为还有其他可能的遗漏,无论是从循环还是我如何处理Connect/Session/Destination/Consumer循环的想法。

有没有人有任何想法什么可能是安全地处理连接问题,必然发生的正确方法?

+0

我没有工作与ActiveMQ,所以我不能帮你在那里,但当你说你在代码中有'while(true)'时,我真的很害怕。如果Spring bean需要启动线程,连接到套接字,那么你应该实现SmartLifecyle,当context被刷新并关闭时,spring将自动调用start和stop。通常情况下,你有一个'private volatile boolean shutdown',在线程成功启动后设置为true,停止设置'shutdown = false',并且在你的线程中你有'while(!shuitown)'。 –

+0

@KlausGroenbaek我已经看过很多'while(!shutdown)'样式循环来处理退出。这是东西的东西todo旁边的东西:)一次一个步骤。感谢您关于SmartLifecycle的建议,我会解决的。检查出。 – Walls

回答

0

似乎在URI中重新连接字符串是非常有用的。这有助于保持连接的连贯性。我结束了在Spring中使用DefaultMessageListenerContainerMessageListenerAdapter,并使用TaskExecutor来处理队列的“观察”。这使得使用Spring进行监控,并消除了需要更高线程来处理队列上的循环。

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

将容器启动移入其自己的线程,以便它可以与应用程序异步完成,并且在连接未准备就绪时不会阻止。这使得该应用启动就好了(排队向上或向下),然后再连接时,它可以补充在监听器来处理任何消息进来。

没有讨厌的while循环需要:)