來源:捕風 發(fā)布時間:2018-12-08 14:56:57 閱讀量:1260
分析這個問題的過程還是挺曲折,如果不想看繁瑣的分析過程,請直接跳到結論
我們小組的成員請耐心看一下過程,積累一下經驗,到用戶現場是能學習很多東西的,以后你們要爭取到用戶現場,呵呵
---------------------------------------------------------------------------------------------------------------------------------------------------------
周一下午到移動時發(fā)現服務器的情況是這樣的
1.ESServer內存達到差不多200M,且以緩慢的速度不斷上升,ESServer進程一直占用CPU約6%-10%
2.服務器生成了一堆大小為0KB的DUMP
3.有大量因沒有管理網段的客戶端不斷地每隔一分鐘取策略
4.日志只有很少
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
在現場解決了兩個問題
1.配置管理網段,讓客戶端不再取策略,并且重啟ESServer,CPU占用率降了不少,平均1%-2%(且不是一直占用),內存沒有發(fā)現上升(不排除是以更慢的速度上升,要等后面觀察)
2.日志太少的原因是因為INI配置的日志文件只有10M,且只有一個備份,后將參數改為了1G(有一個奇怪的現象是,服務器的日志已經成功寫入文件,但文件的修改時間一直不變)
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
在重啟ESServer服務器時,很“有幸”地遇到一個崩毀,生成了55M的dump,趕緊拿回來分析
1.經過一番分析,發(fā)現崩毀是某個鎖在已經被刪除的情況下還繼續(xù)使用導致
2.分析了代碼,這個鎖在服務器停止前都不會被刪除的,而這次崩毀剛好又是在我停止服務器時發(fā)生的
3.寫個模擬這種情況的測試程序,肯定也能這樣崩毀,但畢竟這個程序不是服務器,只能作出推斷,是多線程造成的問題,當停止服務器時,對象已經銷毀,但還有線程剛好在用這個鎖,這是一個很偶然的情況(T_T)
到這里,發(fā)現這個崩毀竟和之前的周期性崩毀沒多大關系……(我崩毀了……),因為:
1.上面的崩毀是在一個很偶然的情況下發(fā)生的,很難周期性發(fā)生
2.上面的崩毀生成了55M的dump,周期性崩毀只生成了0KB的dump
---------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
問題還是沒有找到,但既然懷疑這部分代碼有多線程問題,就從這里出發(fā)查找:
1.發(fā)現代碼里面這部分用得最多的就是日志模塊,聯系到那天國富跟我說他將日志參數從info改為debug時可能可以加快問題的發(fā)生,我就在服務器專門開兩條線程不斷地寫日志,發(fā)現下面了問題
2.大量的日志寫入,導致待寫入日志的隊列內存不斷升高(因為寫入文件的速度和寫入內存的速度不是一個等級導致的),導致最后因空間不夠,list在pushback的時候發(fā)生崩毀(為何stl會實現成這樣還得深究)
3.以服務啟動時,在崩毀的時候竟然生成了一個0KB的dump,“大喜”,因為這和移動的現象很類似(內存高,0KB的dump)
---------------------------------------------------------------------------------------------------------------------------------------------------------
其實以前天珣的代碼編寫者估計也想到這個問題,他限制了隊列的最大長度是1024,但為什么還會出現這個問題呢,原來又是多線程和判斷不嚴謹的問題,且看下面分析
1.在進入隊列前,會先鎖定然后判斷隊列是否已經滿了,但這個鎖在IsFull()后就解鎖了,就存在如果同時有多線程PUT的時候,大家都做完IsFull()這個函數后再做doPut(),而判斷隊列是否滿又竟然只用了“==”,就造成了隊列大于1024,隊列還會繼續(xù)增加的情況。
2.最簡單的修改方法就是將“==”改為“<=”,雖然沒有改變多線程問題的本質,但足以很好地修復這問題
---------------------------------------------------------------------------------------------------------------------------------------------------------
結論:
1.這個問題估計是一直都存著的,只是需要條件觸犯。在移動,大量客戶端重復取策略,日志文件增長得很快(開了DEBUG更快),內存CPU很高,且和我這里重現的現象很類似,所以現階段只能推斷是這個原因造成的。但不明白的是,建行也出現過大量客戶端重復取策略,卻沒有這種崩毀。
2.現在配了管理網段,客戶端不再重復取策略,日志改為info,增加比較慢,問題應該會有所緩和,國富可先不跟移動說,再觀察那邊服務器情況一段時間。要修復的話只需按上面說的修復即可。
看來多線程的確是一個博大精深的問題,我由此擔憂6694客戶端這么多線程會不會埋著什么雷呢?
一切只是推斷,需要時間驗證,以上權當學習總結
---------------------