記得以前接手過一個Java項目,服務(wù)器程序,直接讓Jar在linux上跑的那種。
這個項目由兩個web服務(wù)組成,也就是兩條Java進程,主進程 xxx.jar,輔助進程 xxx_helper.jar。主進程程序中某些功能依賴于輔助進程提供的服務(wù)。
困擾我們的BUG是在生產(chǎn)環(huán)境中輔助進程xxx_helpler.jar不定時無故崩潰,且無jvm錯誤日志產(chǎn)生,也無被系統(tǒng)本身因為資源損耗嚴(yán)重問題而殺死的記錄。 百思不得其解之下我們只能把問題歸因于是程序存在性能問題而被殺死,至于為什么沒有殺死記錄沒人知道。 當(dāng)時團隊中沒有l(wèi)inux玩的很溜的人,也不會查記錄,通過我們那點粗淺的經(jīng)驗,我們想當(dāng)然的以為程序崩潰就是因為消耗內(nèi)存過多被系統(tǒng)殺死的,因為當(dāng)時跑這個程序的機器內(nèi)存異常緊張,所有人的思路都往這個方向被帶了過去。
我開始優(yōu)化xxx_helper.jar程序的性能,什么緩存、多線程、jvm啟動參數(shù)調(diào)優(yōu)、降低代碼算法事件復(fù)雜的,反正各種折騰,幾乎把代碼全部重寫一遍, 可程序無辜崩潰問題依舊存在 。
為了這個問題我連著好多天吃不好睡不香,做夢都在想辦法解決這個問題。 寫代碼多年,這個問題讓我體驗到前所未有的無力感。 然而,正當(dāng)我無計可施之際, 轉(zhuǎn)機來了。 我無意間打開了重啟主進程xxx.jar的腳本,發(fā)現(xiàn)里面有這么一段
ps aux | grep xxx | awk '{print $2}' | xargs kill -9
這段腳本的作用是,提取進程名稱中有xxx關(guān)鍵字的進程ID, 然后kill之。因為整個腳本的邏輯是先關(guān)閉存在的進程,然后再啟動。
而我的項目主進程xxx.jar和輔助進程xxx_helper.jar名稱中都存在xxx關(guān)鍵字, 也就是說之前xxx_helper.jar這個進程無辜崩潰并不是因為程序本身的原因,而是因為主進程啟動腳本在殺死主進程xxx.jar時一道把xxx_helper.jar也給殺了。
看到這段腳本我整個人呆了,就因為一時疏忽,卻浪費了好幾天的時間, 這跟花了幾千塊錢買到價值幾塊錢的東西是一樣的感受,而且我這還是自己坑自己,這種滋味別提有多難受了。 我當(dāng)時就用38碼的手狠狠的抽打自己40碼的臉,以發(fā)泄內(nèi)心悔恨自責(zé)的情緒。
后來,等冷靜下來以后,我只能安慰自己花了這么多功夫也不是一無所獲,至少程序的性能是被我實實在在優(yōu)化了。 雖然, 這種優(yōu)化對于這個項目是毫無意義的。
通過這個事故我領(lǐng)悟到,對于某些頑固的程序BUG,當(dāng)我們根據(jù)自己想當(dāng)然的經(jīng)驗難以找到形成原因時, 就應(yīng)該跳出問題的本身或者自己尋找BUG的思維框架來思考, 因為造成BUG的原因往往和之前尋找BUG的路徑八竿子打不著。
聯(lián)系客服