Java_內存泄漏_實例1


  版權聲明:本文為博主原創文章,轉載請注明出處。 


  記一次壓測時Java內存泄漏問題的發現過程(2017-08-14)

【前篇】

  ①20170811進行A系統與B系統之間的會話功能進行壓測,加上腳本准備期間的聊天消息,預計累計聊天30w+條消息;

  ②20170814原計划加大量對會話功能進行壓測,情況如下;

【應用表現】

  ①B系統前台打開報錯“504”;

 

  ②查看后台應用CPU情況,CPU利用率高達700+%(8核);

 

  ③查看后台內存情況,持續FullGC,且一次FullGC的時長在9s左右,從這里可以粗略定位CPU高的原因是內存GC問題導致;

 

【查看應用JVM配置】

  ①請教B開發團隊,loader提到應該不是JVM配置引起的問題;

【嘗試進行分析】

  ①嘗試使用jvisualvm進行“堆 dump”,但是因為沒有內存了所以jvisualvm連接后卡死(之前測試可以正確連接並顯示JVM情況);

  ②使用jmap命令“jmap -dump:format=b,file=heap.hprof pid”進行dump,dump文件有16G(修改mat配置,無奈客戶端硬件差);

  ③嘗試shutdown應用后重啟,無法shutdown;最后使用“kill -9 pid”暴力解決無法shutdown的情況,后重啟應用;

【重啟后情況】

  ①使用jvisualvm查看堆內存使用情況,表現為“堆內存持續上升”;

 

  ②重啟1小時后,dump文件進行分析,其中“java.util.concurrent.LinkedBlockingQueue$Node”占用內存高達1G,基本可以判斷存在“內存泄漏”;

 

  “com.best.oasis.B.common.entity.messageTransship.MessageTransship”對象151MB,且有160w個MessageTransship對象;

  ③B開發Review代碼:原因所在:線程池中等待執行的任務隊列存在內存泄漏的問題;

正常情況:

  A應用服務器發送消息給B服務器后,B服務器接收消息后將該消息存於中間表B_messagetransship中,同時將該消息轉發給B客服端,B客服端接收消息並對該條消息進行ack,ack成功后刪除B_messagetransship中的該條消息。為了防止消息丟失,B有一個定時重發job,用於每隔5s將B_messagetransship表中的消息再次推送一次;

異常情況:

  1.A服務器發送給B服務器的消息存在於B_messagetransship表中后(此時狀態為“PENDING_SEND”),因為網絡/B客戶主動退出等問題,致使B客戶端並未收到來自B服務器的該消息,則該消息的狀態被置為“SEND_FAILED”存在表B_messagetransship中;

  2.A服務器發送給B服務器的消息,B客服端正確收到,但是B客服端發送的ACK請求返回失敗,則該消息的狀態被置為“PENDING_ACK”存在表B_messagetransship中;

失敗消息定時重發實現邏輯:

  每隔5s從B_messagetransship中逐個取出失敗的消息記錄,以鏈式隊列的形式鏈接在等待執行的任務隊列中,若5s內該消息被線程處理且推送狀態為成功,則刪除數據庫表中該消息記錄;若5s內該消息被線程處理但推送狀態為失敗,則數據庫表中的該條消息記錄保持不變;若5s內該消息並未來得及被線程處理,下一次定時重發任務觸發時,該消息會保留第二個拷貝在待處理任務隊列中,以此類推;

bug發現的誘因:

  B_messagetransship表失敗推送的消息量比較大,B_messagetransship表11w+條數據,失敗消息量大的原因:

  ①11907條“再見”,狀態為:SEND_FAILED

  產生原因:B客戶端對話完畢未接收到再見語,就發起了“{"type":"close","sid":"${sid}"}”的請求,該現象在實際中也可能產生;

  ②17120條“很高興為您服務”,狀態為:PENDING_ACK

  產生原因:壓測腳本未對“很高興為您服務”消息進行ack;

  ③剩余的8w+條,為A發送給B的對話消息,推測是在腳本准備期間產生的數據;

開發下期優化思路:

  ①為B_messagetransship表中的消息增加生存時長,若超時則直接刪除;

  ②限制待執行任務隊列中messageTransship對象的數量,達到一定個數則不再從B_messagetransship中獲取;

測試腳本修改:

  ①增加對“開始語”與“結束語”消息的ack;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM