日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一次生产的 JVM 优化案例

發布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一次生产的 JVM 优化案例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景


生產環境有二臺阿里云服務器,均為同一時期購買的,CPU、內存、硬盤等配置相同。具體配置如下:

節點CPU內存硬盤其它
A2CPU4G普通云盤Centos6.4 64位+JDK1.8.0_121
B2CPU4G普通云盤Centos6.4 64位+JDK1.8.0_121

由于這二服務器硬件和軟件配置相同,并且運行相同的程序,所以在Nginx輪詢策略均weight=1,即平臺的某個流量由這二臺機器平分。

有一次對系統進行例行檢查,使用PinPoint查看下服務器”Heap Usage”的使用情況時,發現,在有一個系統Full GC非常頻繁,大約五分鐘一次Full GC(如果不明白Full GC的什么意思的,請自行百度),嚇我一跳。這么頻繁的Full GC,導致系統暫停處理業務,對系統的實時可用性大打折扣。我檢查了一下Tomcat(Tomcat8.5.28)配置,發現在tomcat沒有作任何關于JVM內存的設置,全部使用默認模式。

?

GC數據


在業務高峰期間,通過PinPoint觀察的A、B節點的”Heap Usage”使用情況,分別進行以下幾個時間段數據。

3小時圖:

上圖B系統在三個小時內,一共發生了22次Full GC,大約每8分鐘進行一次Full GC。每次Full GC的時間大概有150ms左右,即B系統在三個小時內,大約有3300ms暫停系統運行。從上圖來看,堆的空間最大值在890M左右,但在堆空間的大小大約200M就發生Full GC了,從系統資源的利用角度來考慮,這個使用率太低了。

上圖A系統在3個小時內,一共發生了0次Full GC,嗯,就是沒有任何停頓。 在這3小時,系統一直在處理業務,沒有停頓。堆的總空間大約1536m,目前堆的空間大于500M。

6小時圖:

上圖B系統在6個小時的數據統計和3個小時很像,6個小時內一共發生了N次Full GC,均是堆的空間小于200M就發生Full GC了。

上圖A系統在6個小時內,一共發生了0次Full GC,表現優秀。

12小時

上圖B系統在12個小時內,一共發生了N次Full GC,左邊Full GC比較少,是因為我們的業務主要集中白天,雖然晚上屬于非業務高峰期間,還是有Full GC。

上圖A系統在12個小時內,一共發生了0次Full GC,表現優秀。

?

GC日志


看下gc.log文件,因為我們兩臺服務器都輸出了gc的詳細日志,先看下B系統的Full GC日志。

上圖全部是” [Full GC (Ergonomics)”日志,是因為已經去掉” GC (Allocation Failure)”日志,這樣更方便觀察和分析日志,選取GC日志文件最后一條Full GC日志。

2018-12-24T15:52:11.402+0800: 447817.937: [Full GC (Ergonomics) [PSYoungGen: 480K->0K(20992K)] [ParOldGen: 89513K->69918K(89600K)] 89993K->69918K(110592K), [Metaspace: 50147K->50147K(1095680K)], 0.1519366 secs] [Times: user=0.21 sys=0.00, real=0.15 secs]

可以計算得到以下信息:

堆的大小:110592K=108M

老年代大小:89600K=87.5M

新生代大小:20992K=20.5M

分析:這次Full GC是因為老年代對象占用的空間的大小已經超過老年代容量 ([ParOldGen: 89513K->69918K(89600K)])引發的Full GC。是因為分配給老年代的空間太小,遠遠不能滿足系統對業務的需要,導致老年代的空間常常被占滿,老年代的空間滿了,導致的Full GC。由于老年代的空間比較小,所以每次Full GC的時間也比較短。

A系統日志,只有2次Full GC,這2次GC均發生在系統啟動時:

7.765: [Full GC (Metadata GC Threshold) [PSYoungGen: 18010K->0K(458752K)] [ParOldGen: 15142K->25311K(1048576K)] 33153K->25311K(1507328K), [Metaspace: 34084K->34084K(1081344K)], 0.0843090 secs] [Times: user=0.14 sys=0.00, real=0.08 secs]

可以得到以下信息:

堆的大小:1507328K=1472M

老生代大小:1048576K=1024M

新生代大小:458752K=448M

分析:A系統只有系統啟動才出現二次Full GC現象,而且是” Metadata GC Threshold”引起的,而不是堆空間引起的Full GC。雖然經過一個星期的觀察,A系統沒有Full GC,但一旦發生Full GC時間則會比較長。其它系統增加發現過,1024M的老年代,Full GC持續的時間大約是90ms秒。所以看得出來推也不是越大越好,或者說在UseParallelOldGC收集器中,堆的空間不是越大越好。

?

分析與優化


總體分析:

  • B系統的Full GC過于頻繁,是因為老生代只有約108M空間,根本無法滿足系統在高峰時期的內存空間需求。由于ParOldGen(老年代)常常被耗盡,所以就發生Full GC事件了。

  • A系統的堆初始空間(Xms)和堆的最大值(Xmx)均為1536M,完全可以滿足業務高峰期的內存需求。

  • 優化策略:

  • B系統先增加堆空間大小,即通過設置Xms、 Xmx值增加堆空間。直接把Xms和Xmx均設置為1024M。直接堆的啟動空間(Xms)直接設置為堆的最大值的原因是:因為直接把Xms設置為最大值(Xmx)可以避免JVM運行時不停的進行申請內存,而是直接在系統啟動時就分配好了,從而提高系統的效率。把Xms(堆大小)設置為1024M,是因為采用JDK的建議,該建議通過命令得到” java -XX:+PrintCommandLineFlags -version” 。

    其中,“-XX:MaxHeapSize=1004719104”,即Xmx為1024M,其它建議暫時不采納。所以綜合下來的B系統的JVM參數設置如下:export JAVA_OPTS="-server –Xms1024m -Xmx1024m -XX:+UseParallelOldGC -verbose:gc -Xloggc:../logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

  • A系統JVM參數設置保持不變,以便觀察系統運行情況,即:export JAVA_OPTS="-server -Xms1536m -Xmx1536m -XX:+UseParallelOldGC -verbose:gc -Xloggc:../logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

  • 將A、B節點系統的JVM參數采用2套參數,是為了驗證A或B的參數更適合實際情況。

  • 總結

    以上是生活随笔為你收集整理的一次生产的 JVM 优化案例的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。