某服務有兩臺機器,每隔幾天會報警load高,一開始看監控發現gc時間抖動很大,以為是發生了fullgc引起卡頓而未加注意,之后登入線上機器查看日志發現是jvm崩潰導致了服務重啟從而引發gc時間抖動。以某天為例,該服務分別在上午7點和上午10點發生jvm崩潰,如果同時發生崩潰將導致線上停服,后果不堪設想。
2 問題分析崩潰日志顯示jvm崩潰發生在在標記清除掃根路徑時。
搜索此bug,發現是jvm的一個已知bug,https://bugs.openjdk.java.net/browse/JDK-8020236,這個bug在1.6和1.7中均有,只是因為重現困難而一直未被修復。
Par_MarkFromRootsClosure::scan_oops_in_oop(HeapWord*)
有人遇到和我們一樣的問題(http://hllvm.group.VEvb.com/group/topic/43404),他通過壓測發現當“ParallelCMSThreads > ParallelGCThreads”會引起此崩潰,而當"ParallelCMSThreads <= ParallelGCThreads"時問題不再復現。而“ParallelCMSThreads > ParallelGCThreads”這個問題也在jvm bug列表中(https://bugs.openjdk.java.net/browse/JDK-6668573),此bug下有人給出的解決思路是將ParallelCMSThreads 設置為 <=ParallelGCThreads。
3 解決方法查看我們junglepoi-service服務的jvm參數配置,發現ParallelCMSThreads被設置成4,而ParallelGCThreads卻未被設置。默認情況下ParallelGCThreads = (ncpus <= 8) ? ncpus : 3 + ((ncpus * 5) / 8),其中ncpus是機器的核數,由于junglepoi-service服務所在的機器為2核4G配置,因此默認情況下ParallelGCThreads=2,此時ParallelCMSThreads > ParallelGCThreads。
解決方法是:1)將ParallelCMSThreads設置為2或1;2)或者不設置ParallelCMSThreads,默認情況下ParallelCMSThreads = (ParallelGCThreads + 3) / 4,如果不設置默認ParallelCMSThreads=(2+3)/4=1。
我們將ParallelCMSThreads設置為2,上線兩天未復現jvm崩潰異常,后續將持續觀察。
4 啟示不能簡單拷貝其它項目的jvm參數配置,需要結合項目特點、機器環境等各方面信息來綜合配置。
新聞熱點
疑難解答