天天看點

解決ActiveMQ的“Invalid broker URI”異常的曆程

最近碰到一個問題,把解決的過程記錄下來。

同僚的應用上線,tomcat無法正常啟動。抛出這樣的異常:

據同僚說,線上下環境,可以正常運作,線上上環境就出錯了,非常的詭異。

程式有一個env.properties的配置檔案:

broker.producer  = failover://(nio://10.0.0.3:91615?connectiontimeout=3000,nio://10.0.0.4:91615?connectiontimeout=3000)

線上和線下加載的是不同的env.properties。

在spring xml配置檔案裡有這樣的配置:

spring在運作時,會自動替換${}表達式裡的值。

線上上機器上,執行

telnet 10.0.0.3 91616

可以正常連接配接,再到activemq的web console上檢視connection,發現的确沒有這個ip的連接配接。

線上的配置的brokeruri是這個:

failover://(nio://10.0.0.3:91616?connectiontimeout=3000,nio://10.0.0.4:91616?connectiontimeout=3000)

直接先改為最簡單的,在vim下yy複制了一行,删除多餘的,剩下:

nio://10.0.0.3:91616

發現還是報異常。

在本地跑了個簡單程式,用xshell的端口轉發,把本地請求轉發到線上機器上,發現可以正常發送消息。于是讓同僚回去檢查代碼裡的其它問題了。

但是同僚沒有找到錯誤,于是把剛才的簡單的程式打成一個fat jar包,放到線上機器上去跑,發現可以正常發送activemq消息。

程式打包用的是maven的one jar 插件,參考:

http://www.mkyong.com/maven/maven-create-a-fat-jar-file-one-jar-example/

把測試程式放到同僚的war包的代碼裡,放到線上機器,發現可以正常發送消息。

但是同僚配置的activemq還是不能發送消息,還是報“invalid broker uri”異常。

沒辦法了,把同僚的環境變量${broker.producer},設定到測試代碼裡,發現測試代碼抛異常了。

于是确認是${broker.producer} 這個變量有問題。

但是env.properties檔案裡的配置看起來是對的。于是懷疑是配置檔案格式有問題。

備份舊檔案,建了個新配置檔案,配置上

broker.producer =nio://10.0.0.3:91615

發現,居然正常了。

于是對比兩個配置檔案,發現舊的配置檔案上,最後多了一個空格。。就是91615後面多了一個空格。

蛋疼無比,activemq居然不能識别處理配置值後面多出來的一個空格。而且spring抛出來的異常裡也沒有這個資訊。

開始調試時,找不到原始的異常資訊在哪裡,spring的函數調用層次太多了。于是采用代碼搜尋。

在 https://searchcode.com 搜尋"invalid broker uri",終于找到原始的異常資訊是下面的代碼抛出來的:

很奇怪的是,illegalargumentexception異常裡是正确地把urisyntaxexception設定到cause裡了,後面的spring卻沒有把這個資訊給列印出來。。

為什麼spring能把前面的異常資訊都列印出來,而原始的異常資訊卻不能列印出來?比如某個spring異常資訊是這樣的:

caused by: org.springframework.beans.propertybatchupdateexception; nested propertyaccessexceptions (1) are:

srping會用caused by,nested exception is,這樣的字元把所有的異常都串起來。到底這裡面是怎麼工作的?

再次搜尋"nested exception is"

查找到spring相關的代碼。

原來所有的spring異常類都繼承自nestedruntimeexception,而nestedruntimeexception重寫了getmessage()函數,在getmessage()函數裡,會把異常的資訊全都串起來。

而illegalargumentexception繼承自throwable類,throwable類的getmessage()函數隻是簡單列印了message,并沒有把cause也輸出。

nestedexceptionutils這個類是abstract,這樣可以防止使用者得到執行個體,這樣使用者不能用錯。這個也是一個常見的util類的技巧了。

這個代碼搜尋網站比較好用:https://searchcode.com

很多流行網站的資料都有,比github上要全。

後來在網上搜尋了下“invalid broker uri”,有10萬多條結果。。估計有不少就是因為一些空格而造成的。。

activemq的開發者隻需要加上一點點的trim()的判斷處理代碼,就可以減少很多人的痛苦了。

是以防禦性程式設計還是有必要的,有的時候并不真的是使用者不會用,而是錯誤來自想像不到的地方。