1、問題發現
Prometheus報警user-center服務的Old GC過多,需要排查
2、問題分析
user-center服務生產環境部署4個結點,整個堆的大小設置為2g,新生代的大小設置為1g。這次的報警,4個結點都有報,查看其中一個結點發現該結點,從10點30分左右到11點20分左右,不到一個小時的時間里,竟然產生了5次Full GC,這個是極其不正常的。
3、使用GCViewer分析GC日志
可以看出,整個老年代1g的內存,幾乎已經全部被占用了,而且在Full GC之后,並沒有回收多少內存,很顯然,內存泄漏了。內存泄漏導致老年代內存空間不足,新生代的對象到了一定的年齡,需要提升,提升時發現老年代內存不夠,就進行Full GC,但每次Full GC之后,並沒用回收多少內存,雖然並沒有導致OOM,但是很快下次提升就又需要Full GC了。
4、dump堆快照文件
使用命令jinfo -flag +HeapDumpBeforeFullGC 28679
和jinfo -flag +HeapDumpAfterFullGC 28679
,在Full GC之前和Full GC之后dump堆內存快照(注意:dump完成之后,一定要關閉這兩個參數,不然頻繁Full GC 導致頻繁dump,會占用大量磁盤空間);使用命令jinfo -flag -HeapDumpBeforeFullGC 28679
和jinfo -flag -HeapDumpAfterFullGC 28679
關閉兩個參數。其實也可以不用非要加上這兩個參數然后等待Full GC的出現,由於是內存泄漏,老年代內存不能回收,那么直接使用命令jmap -dump:format=b,file=before.hprof 28679
和
jmap -dump:live,format=b,file=after.hprof 28679
來dump堆快照文件也是可以的,加上live表示只保存存活對象。
5、使用Eclipse MAT分析對快照
很顯然可以看到堆內存被對象DoctorInvitePictureManagerImpl
占用了811.8M,就是它導致了內存泄漏。剩下的就需要業務同學排查代碼了。