2017-02-10 55 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循環需要:)