一個畢生難忘的BUG

記得以前接手過一個Java項目,服務器程序,直接讓Jar在linux上跑的那種,

 

這個項目由兩個web服務組成,也就是兩條Java進程,主進程 xxx.jar,輔助進程 xxx_helper.jar。主進程程序中某些功能依賴於輔助進程提供的服務。

 

困擾我們的BUG是在生產環境中輔助進程xxx_helpler.jar不定時無故崩潰,且無jvm錯誤日誌產生,也無被系統本身因爲資源損耗嚴重問題而殺死的記錄。 百思不得其解之下我們只能把問題歸因於是程序存在性能問題而被殺死,至於爲什麼沒有殺死記錄沒人知道。 當時團隊中沒有linux玩的很溜的人,也不會查記錄,通過我們那點粗淺的經驗,我們想當然的以爲程序崩潰就是因爲消耗內存過多被系統殺死的,因爲當時跑這個程序的機器內存異常緊張,所有人的思路都往這個方向被帶了過去。

 

我開始優化xxx_helper.jar程序的性能,什麼緩存、多線程、jvm啓動參數調優、降低代碼算法事件複雜的,反正各種折騰,幾乎把代碼全部重寫一遍, 可程序無辜崩潰問題依舊存在 。

 

爲了這個問題我連着好多天吃不好睡不香,做夢都在想辦法解決這個問題。 寫代碼多年,這個問題讓我體驗到前所未有的無力感。 然而,正當我無計可施之際, 轉機來了。 我無意間打開了重啓主進程xxx.jar的腳本,發現裏面有這麼一段

 

ps aux | grep xxx | awk  '{print $2}' | xargs kill -9

 

這段腳本的作用是,提取進程名稱中有xxx關鍵字的進程ID, 然後kill之。因爲整個腳本的邏輯是先關閉存在的進程,然後再啓動。

 

而我的項目主進程xxx.jar和輔助進程xxx_helper.jar名稱中都存在xxx關鍵字, 也就是說之前xxx_helper.jar這個進程無辜崩潰並不是因爲程序本身的原因,而是因爲主進程啓動腳本在殺死主進程xxx.jar時一道把xxx_helper.jar也給殺了。

 

看到這段腳本我整個人呆了,就因爲一時疏忽,卻浪費了好幾天的時間, 這跟花了幾千塊錢買到價值幾塊錢的東西是一樣的感受,而且我這還是自己坑自己,這種滋味別提有多難受了。 我當時就用38碼的手狠狠的抽打自己40碼的臉,以發泄內心悔恨自責的情緒。

 

後來,等冷靜下來以後,我只能安慰自己花了這麼多功夫也不是一無所獲,至少程序的性能是被我實實在在優化了。 雖然, 這種優化對於這個項目是毫無意義的。

 

通過這個事故我領悟到,對於某些頑固的程序BUG,當我們根據自己想當然的經驗難以找到形成原因時, 就應該跳出問題的本身或者自己尋找BUG的思維框架來思考, 因爲造成BUG的原因往往和之前尋找BUG的路徑八竿子打不着。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章