做乙個小專案時,選擇使用 activemq 作為中介軟體,負責專案內各元件的通訊。
剛部署時,整個專案執行正常。執行 n 天後,發現 activemq 出乎意料地自動重啟,進而導致佇列中未來得及消費的資料丟失。
剛開始,以為是配置檔案 activemq.xml 的問題,但是仔細核查後,發現沒有什麼明顯的錯誤配置。然後,懷疑是否是 activemq 版本的問題,因此另選了一台測試機器進行其他版本的測試,結果發現還是出現同樣的異常現象。至此,基本可以排除配置和版本的問題,只能從日誌或其他途徑,去排查問題的根源。
尋找問題時,首先能想到的自然是排查日誌檔案。但是在檢視 activemq 日誌的時候,很詭異的現象出現了。activemq 每一次異常重啟時,日誌並沒有輸出任何內容,只有輸出正常啟動時所展示的堆疊資訊。這一下問題就變得比較棘手了,沒有異常丟擲,那麼該如何定位問題的根源?
考慮過閱讀 activemq 的原始碼,來推理問題的產生原因,但因為專案相對較急,只能作罷。
束手無策之際,突然想到是否會與機器記憶體有關?畢竟專案程式所在機器的配置較低。思慮至此,馬上使用jstat
和jmap
觀察 activemq 的 jvm 情況。然後,再一次發現了詭異的現象。activemq 執行期間,每一次老年代記憶體區耗盡觸發 fgc 時,老年代的記憶體並沒有釋放,反而是申請了更多的記憶體空間,因此隨著 activemq 的執行時間增長,老年代所佔空間也越來越大,直至達到限制的最大記憶體時,activemq 崩潰重啟。
這一下,問題的根源總算是找到了,但是,新的問題也隨之而來。由於專案較小,佇列中的訊息都能夠及時被消費者消費掉,理論上不存在記憶體持續增長的可能,那麼,究竟是什麼造成了老年代記憶體占用不斷增加?再次檢查了一遍配置檔案,依舊毫無收穫。
此時,似乎已山窮水盡。突然,乙個憑空而現的想法提供了新的思路。會不會問題壓根就不是出在 activemq 本身,而是出現在客戶端**?思路一通,馬上檢視了專案中與 activemq 相關的**,發現了乙個可疑的地方。**中使用 session 收發訊息後,並沒有 close 掉。那麼,會不會有這種可能?由於客戶端沒有關閉會話,服務端會一直保持著這個 session,導致該 session 下持有的物件一直存在著引用,不會被 gc **,進而導致記憶體不被釋放,最後引發崩潰。這樣一想,一切似乎都說得通了。在客戶端**中新增上 session 的 close 方法,更新到集群後,再一次持續觀察 activemq 的狀態。這一次,一切都恢復了正常,老年代內存在 fgc 觸發後成功釋放,activemq 也不再莫名其妙重啟了。
至此,問題總算解決。然而,內中緣故,還不是理解很透徹,後續還需抽空深入了解才是。
記一次Android Studio編譯異常
最近電腦總是藍屏,所以重灌了一次win7系統,然後重新安裝android studio,然後發現在build的時候一直報乙個錯誤 a failure occurred while executing com.android.build.gradle.tasks.mergeresources file...
記一次xxljob異常排查
我們使用開源的xxljob封裝了乙個job服務作為平台的job元件。有乙個專案組生產上總是隔些天就會有一次異常發生,排程失敗,且沒什麼報錯資訊。jobadmin 執行器服務都是三颱伺服器集群部署,且資料庫是三颱集群讀寫分離部署。後排查發現如下 失敗的那次任務時間點上排程時,執行器服務列表是空的,導致...
記一次keepalived的異常問題
背景 2019一月份我對我們專案的開發環境及測試環境,做了一次資料庫災備及高可用方案,mysql採用的是主主複製 keepalived機制 虛擬ip採用的是 225 mongodb採用的是複製集模式。問題 從1月20號上測試環境至3月27都沒出現任何問題。結果3月28日早上,相繼有人告訴我,虛擬ip...