JDK8之MetaspaceSize配置導致頻繁FullGC

轉載自:掘金網【小妍品品】-JDK8之MetaspaceSize配置導致頻繁FullGC

前言

新系統上線,由於測試環境機器配置太低,所以單獨找了一臺預發機做接口壓測,但是QPS達到30時候cpu就滿了,簡直慌了,新系統這麼垃圾的麼~

背景介紹

新的賬務系統,角色定位是內部戶機構賬,所以根據不同的金融交易場次會有一次記賬請求中存在多借多貸,也就是一次請求會出現給18個賬戶在一個事務中做記賬處理,可想這裏面會有多少要注意的坑,詳細的不做展開

找問題

top 命令

在這裏插入圖片描述
因爲這個接口實現上多次用到數據庫悲觀鎖select for update,最初還以爲是代碼程序性能低導致的。但是看下qps才30… 涼了~

top -Hp pid 發現下面均是某個進程cpu使用率高

在這裏插入圖片描述
找到該pid下cpu佔用最高的tid,然後通過 jstack pid | grep tid -A 30 找到對應的進程信息

printf ‘%x\n’ 12149 tid 轉換16進制

在這裏插入圖片描述

jstack pid | grep tid 查看該線程信息。好了,不用往下瞅了,FullGC的進程~

在這裏插入圖片描述

jstat -gcutil pid 1000 10

在這裏插入圖片描述
這時候看到新生代、老年代的佔用率都非常低,但是還是在不斷的FullGC (這時候其實是知識點的缺失,平常沒有過於去關注M、CCS這兩列的值,想當然認爲這是某項指標的適用率,因爲佔比90%左右,所以沒有太在意~) ,單單看新老代的數據不應該會觸發FullGC啊!!!

然後稀裏糊塗的把堆詳細信息都給打出來了~,看下依舊不是這塊問題(使用率確實非常低)。

jmap -heap pid

 
Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 1073741824 (1024.0MB)
   NewSize                  = 235929600 (225.0MB)
   MaxNewSize               = 235929600 (225.0MB)
   OldSize                  = 837812224 (799.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 134217728 (128.0MB)
   CompressedClassSpaceSize = 125829120 (120.0MB)
   MaxMetaspaceSize         = 134217728 (128.0MB)
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 212336640 (202.5MB)
   used     = 0 (0.0MB)
   free     = 212336640 (202.5MB)
   0.0% used
Eden Space:
   capacity = 188743680 (180.0MB)
   used     = 0 (0.0MB)
   free     = 188743680 (180.0MB)
   0.0% used
From Space:
   capacity = 23592960 (22.5MB)
   used     = 0 (0.0MB)
   free     = 23592960 (22.5MB)
   0.0% used
To Space:
   capacity = 23592960 (22.5MB)
   used     = 0 (0.0MB)
   free     = 23592960 (22.5MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 837812224 (799.0MB)
   used     = 95685920 (91.25320434570312MB)
   free     = 742126304 (707.7467956542969MB)
   11.420926701589877% used

41909 interned Strings occupying 5041832 bytes.

還在一臉懵逼 ··· ···

這時候有個小夥伴提到了元空間內存滿了,恍惚,回過頭去查了下 M、CCS 明明是93.19%、90.48% 怎麼就滿了呢??

那麼jstat -gcutil 命令展示列的 M、CCS 到底是啥? 好吧把定義貼出來:

column {
    header "^M^"  /* Metaspace - Percent Used */
    data (1-((sun.gc.metaspace.capacity - sun.gc.metaspace.used)/sun.gc.metaspace.capacity)) * 100
    align right
    width 6
    scale raw
    format "0.00"
  }
  column {
    header "^CCS^"    /* Compressed Class Space - Percent Used */
    data (1-((sun.gc.compressedclassspace.capacity - sun.gc.compressedclassspace.used)/sun.gc.compressedclassspace.capacity)) * 100
    align right
    width 6
    scale raw
    format "0.00"
  }

也就是說M是表示metaspace的使用百分比??事實證明並非如此~
通過jstat -gccapacity pid 看下具體的metaspace空間值,如下圖:

jstat -gccapacity pid

在這裏插入圖片描述
MC空間大小是131072KB=128M 然後通過 jstat -gc pid 發現 MC(元空間大小)、MU(元空間使用大小)兩列的值居然都不是是131072(此處沒截圖)。

說明:下面兩張圖是預發環境配置修改後的數值,跟當時定位問題時候數值不一樣,此處爲了說明 MC\MU並不是jdk的環境變量配置的MetaspaceSize 。並且使用jstat -gcutil執行出來的結果M 的百分比並不代表觸發 FullGC的閾值~

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

後來通過網上找到說jdk的環境變量的配置-XX:MetaspaceSize=128m 這纔是觸發元空間FullGC的條件,對比了下線上分配百分比,所以先找到運維把預發環境的環境變量-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m部分 都配置成256m(至於爲啥是256,明天可以根環境據修改後的壓測分時數據再做下說明),按照原來的並變量發數再壓一次, 果然沒有再出現堆使用率很低並且還在不配置停FullGC的現象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章