JVM調優—減少FullGC

背景

????????最近負責了一個審批流程新項目,帶領了幾個小伙伴,哼哧哼哧的干了3個月左右,終于在三月底完美上線了,好消息是線上客戶用的很絲滑,除了幾個非常規的業務提單之外,幾乎沒有什么大的問題,但是美中不足的是,發現每個pod的GC頻率非常高,基本上30分鐘就會有一次FGC,導致每次流量高峰的時候,會有一部分客戶反饋,系統有些卡頓,觀察監控平臺發現,每天流量高峰的時候FGC竟然達到了驚人的5分鐘每次,每次GC的時間差不多有400-700ms,此時,部分接口的耗時達到了5s,因此接口優化和參數調優迫在眉睫;
????????因為本項目是基礎服務,每個業務方都會調用,所以當時申請節點內存大小的時候就富裕了一點,共部署了4個pod,每個pod資源是8核16G,但是觀察監控平臺發現,每個pod內存只使用不到2G,其中eden 200M old 500m survivor更是只有可憐的96m左右,導致年輕代很容易就占滿了,存活的對象就被轉移到老年代了,由于老年代分配的內存也特別少,QPS一高就會頻繁的觸發FullGC,導致系統卡頓甚至接口超時。
????????排查代碼發現有一個占比60%量一個接口雖然查詢的表比較單一,但是查詢了所有字段,其中一個字段存儲的是一個JSON,但業務中卻又沒有使用到。

JVM常見參數

一、配置垃圾收集器

1、Serial垃圾收集器(新生代)

?????????開啟:-XX:+UseSerialGC

?????????關閉:-XX:-UseSerialGC

?????????//新生代使用Serial ?老年代則使用SerialOld

??

?2、ParNew垃圾收集器(新生代)

?????????開啟 -XX:+UseParNewGC

?????????關閉 -XX:-UseParNewGC

?????????//新生代使用功能ParNew 老年代則使用功能CMS

??

?3、Parallel Scavenge收集器(新生代)

?????????開啟 -XX:+UseParallelOldGC

?????????關閉 -XX:-UseParallelOldGC

?????????//新生代使用功能Parallel Scavenge 老年代將會使用Parallel Old收集器

??

?4、ParallelOld垃圾收集器(老年代)

????????開啟 -XX:+UseParallelGC

????????關閉 -XX:-UseParallelGC

????????//新生代使用功能Parallel Scavenge 老年代將會使用Parallel Old收集器

??

?5、CMS垃圾收集器(老年代)

????????開啟 -XX:+UseConcMarkSweepGC

????????關閉 -XX:-UseConcMarkSweepGC

??

?6、G1垃圾收集器

?????????開啟 -XX:+UseG1GC

?????????關閉 -XX:-UseG1GC

二、堆內存相關配置

設置堆初始值

?????????指令1:-Xms2g

??

?設置堆區最大值

?????????指令1:-Xmx2g

??

?新生代內存配置

?????????指令1:-Xmn512m

??

?2個survivor區和Eden區大小比率

?????????指令:-XX:SurvivorRatio=6 ?//S區和Eden區占新生代比率為1:6,兩個S區2:6(默認是8,即8:1:1)

??

?新生代和老年代的占比

?-XX:NewRatio=4 ?//表示新生代:老年代 = 1:4 即老年代占整個堆的4/5;默認值=2

三、GC并行執行線程數

????????-XX:ParallelGCThreads=16

四、進入老年代的GC年齡

?????????-XX:InitialTenuringThreshol=7 //年輕代對象轉換為老年代對象最小年齡值,默認值7,對象在堅持過一次Minor GC之后,年齡就加1,每個對象在堅持過一次Minor GC之后,年齡就增加1

??

?????????-XX:MaxTenuringThreshold=15 //年輕代對象轉換為老年代對象最大年齡值,默認值15

五、GC日志信息配置

????????-Xloggc:/data/gclog/gc.log//固定路徑名稱生成

?????????-Xloggc:/home/GCEASY/gc-%t.log //根據時間生成

????????打印GC的詳細日志?

????????開啟 -XX:+PrintGCDetails

????????關閉 -XX:-PrintGCDetails

六、在Full GC時生成dump文件

????????-XX:+HeapDumpBeforeFullGC ? ? ? //實現在Full GC前dump

????????-XX:+HeapDumpAfterFullGC ? ? ? ?//實現在Full GC后dump。

????????-XX:HeapDumpPath=e:\dump ? ? ? ?//設置Dump保存的路徑


調優過程

? ? 一、業務調優

? ? ? ?業務調優就不展開講述了,主要是用到了arthas這個調優工具,trace了耗時比較久的接口,排除不優雅的編碼之后,就來到了數據層面,由于項目使用的是postgres sql,并且已經分庫+分區了,核心表的數據量級也是百萬級別,所以最終關注的是索引,使用explain查看核心sql的執行計劃,看其是否命中索引;

????????補充一點,由于項目有一張歷史表的數據量比較大,8000萬左右,并且業務中也需要使用到,每個單據號對應的審批流程一般是流程節點的10倍左右,比如某個審批流程10個節點,那么改流程結束后就會產生100+條數據,在列表中使用到了改表中的某些數據,起初直接根據單據號進行查詢,那么分頁條數為1000的時候每次就會查詢1000*100條記錄,而業務真正需要關注的只是10個節點的審批結果而已,白白浪費90%的查詢記錄,因此,在業務中冗余了一個節點字段,標識是否是節點的審批結果,每次查詢除了使用單據號之外,加上該字段,就大大的過濾了記錄數量,這樣做法有如下好處:

? ? ? ? ①減少網絡傳輸量

? ? ? ? ②降低內存使用(起初是內存過濾,高cpu操作)

? ? ? ? ③防止OOM


二、JVM參數調優

? ? ? ? 第一版

? ? ? ? ? ? ? ? 第一版比較偷懶,直接上了G1,因此G1不用配置過多的參數,很多就自適應調節,但是一上線發現cpu就很容易飆升到80以上,并且接口耗時也慢了一倍,起初每個接口的耗時到該200ms,G1之后就變成400ms,終于在運行3天之后,就有監控告警有大量的接口請求超時,觀察到jvm堆內存使用長時間100%,導致健康檢查機制強行將節點重啟了(5s檢查一次,15未檢查到就重啟)為了不影響業務先增加了兩個節點,降低QPS,從而降低堆內存使用。

? ? ? ? ? ? ? ? 具體的參數配置

-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+PrintGC -Xloggc:/data/logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/ -XX:+UseG1GC -Xmx9G -Xms9G -XX:MaxDirectMemorySize=1g -XX:ConcGCThreads=8 -XX:MaxGCPauseMillis=500 

? ? ? ? 第二版

????????由于公司所有的項目都是K8s集群部署,所以JVM參數基本都用的是默認參數,這一次只是設置了Xms=11g,Xmx=10g,Xmn=4g,但是發現年輕代的from和to的比例不對,按照正常的默認8:1:1,應該是410m左右,但是監控上面顯示的始終是121m,這樣的話QPS達到高峰的時候,老年代上升的速率就比較快,3.76G,基本上12h就用完觸發了FGC,這顯然是不合理的,因為業務邏輯中沒有需要常駐內存的對象,基本上朝生夕滅的,在年輕代就應該被回收,而導致出現這個原因是from和to的內存太小了,存貨了15次之后的對象就被轉移到老年代了。

? ? ? ? 開始的時候使用-XX:-UseAdaptiveSizePolicy?–XX:SurvivorRatio=8,確實改變年輕代的具體分配內存,但是使用 jmsp -heap 1命令發現,jvm的垃圾回收器是ParallelGC,并不是我們想要的CMS,因此不論年輕代from和to的設置了多大空間,其使用始終不會超過121m,老年代還是晉升的速率比較快,并沒有徹底解決問題。具體參數配置如下

-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Xmx11g -Xms11g -Xmn5g -XX:PermSize=1g -XX:MaxPermSize=1g -XX:SurvivorRatio=8 -XX:-UseAdaptiveSizePolicy -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps

? ? ? ? 第三版 最終版本

? ? ? 開啟CMS收集參數? -XX:+UseConcMarkSweepGC,監控和運行變得正常,堆空間各個區域的分配也是正常的。

-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+UseConcMarkSweepGC -Xmx11g -Xms11g -Xmn5g -XX:PermSize=1g -XX:MaxPermSize=1g -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:/data/logs/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs

????????小結

? ? ? ? 容器部署節點只分配1G,具體原因可以參考這篇文章頻繁 GC 問題排查以及UseContainerSupport與MaxRAMPercentage的正確使用-CSDN博客

????????按照理論上第二次調優就已經能夠滿足業務需求了,但是依據《深入理解Java虛擬機》講的,jdk8默認的垃圾收集器是CMS,那么年輕代的eden、from和to分配內存空間的比例應該是8:1:1,顯然目前我的數據不正確,進入到pod節點發現jvm使用的是ParallelGC,如下圖所示


jvm調優常見問題

? ? ? ? 常用命令

? ? ? ? jmap -heap pid 查看內存使用情況

推薦配置

????????8C16G下的參數配置

綜上所述,8C16G下,推薦使用如下的參數設置:

-Xmx12g -Xms12g

-XX:ParallelGCThreads=8

-XX:ConcGCThreads=2

-XX:+UseConcMarkSweepGC

-XX:+UseCMSInitiatingOccupancyOnly

-XX:CMSInitiatingOccupancyFraction=70

-XX:MaxGCPauseMillis=100 ?// 按業務情況來定

-XX:+PrintGCTimeStamps

-XX:+PrintGCDetails

-XX:+PrintGCDateStamps

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/9817.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/9817.shtml
英文地址,請注明出處:http://en.pswp.cn/web/9817.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

行駛證OCR識別接口怎么對接

行駛證OCR識別接口也叫行駛證文字識別OCR接口,指的是傳入行駛證照片,精準識別靜態行駛證圖像上的文字信息。那么行駛證OCR識別接口怎么對接呢? 首先我們找到數脈API,然后注冊賬戶,購買免費套餐 然后就需要公司的技術大牛把行駛證文字識別OCR…

gdb調試功能描述

gdb調試功能描述 gdb 調試:只對可執行文件進行調用,無法直接用gdb調試.c文件 1.查找命令幫助: (gdb) help data (gdb) help call -l (list) 查看載入文件(默認為10行&#xff09…

短信群發公司通道有哪些要求

短信群發公司通道有哪些要求 網絡穩定性 短信群發公司的通道在進行時需要具備良好的網絡穩定性。這意味著通道需要能夠穩定連接到互聯網,并具備高速傳輸能力。在網絡不穩定或者傳輸速度慢的情況下,可能會受到影響,甚至導致失敗。 高可靠性 …

linux - 主次設備號自動申請

alloc_chrdev_region 原型如下,該函數向內核申請一個空閑的主設備號。 alloc_chrdev_region(&g_aputriger_dev, 0, APUTRIGER_MAX_NUM, "aputriger0"); 第四個參數是我們使用cat /proc/devices 看到的名稱 /*** alloc_chrdev_region() - register a…

持續總結中!2024年面試必問 100 道 Java基礎面試題(四十)

上一篇地址:持續總結中!2024年面試必問 100 道 Java基礎面試題(三十九)-CSDN博客 七十九、Java泛型中的T、R、K、V、E分別指什么? 在Java泛型中,T、R、K、V 和 E 是類型參數的常見占位符,它們用…

Babylon.js 7.0開發入門教程

Babylon.js 是一個功能強大的開源 3D 引擎,能夠使用 JavaScript 渲染交互式 3D 和 2D 圖形。它是為 Web 甚至 VR 創建游戲、演示、可視化和其他 3D 應用程序的絕佳選擇。Babylon.js最新版本是7.0。 Babylon.js 是免費、開源和跨平臺的,是 Unity 和 Unre…

LeetCode 每日一題 ---- 【1463.摘櫻桃 II】

LeetCode 每日一題 ---- 【1463.摘櫻桃 II】 1463.摘櫻桃II方法:動態規劃(遞推) 1463.摘櫻桃II 方法:動態規劃(遞推) 昨天是摘櫻桃I,今天是II,與昨天的區別主要在于,今…

【進程替換】多進程程序替換原理 | 進程程序替換函數 | execlexecv | execlpexecvp

目錄 多進程程序替換 多進程程序替換原理 進程程序替換函數詳解 execl&execv execlp&execvp execle&execvpe execve 多進程程序替換 我們想要進程替換的同時不影響舊的進程(使用多進程版)fork創建子進程,讓子進程去替換執…

2008NOIP普及組真題 4. 立體圖

線上OJ: 一本通-1977:【08NOIP普及組】立體圖 核心思想: 本題采用模擬方法一個一個畫小方塊(雖然畫的是立體空間的積木,但本質還是在二維平面上畫圖形) 本題的難點在于: 1、如何確定二維平面畫…

tengine-docker鏡像制作

1.下載 wget https://tengine.taobao.org/download/tengine-3.0.0.tar.gz 或者直接下載這個包括下邊兩個配置文件了 https://download.csdn.net/download/cyw8998/89286114 2.編輯nginx.conf文件 #####user nobody; worker_processes 1;#error_log logs/error.log; #er…

淺析擴散模型與圖像生成【應用篇】(二十三)——Imagic

23. Imagic: Text-Based Real Image Editing with Diffusion Models 該文提出一種基于文本的真實圖像編輯方法,能夠根據純文本提示,實現復雜的圖像編輯任務,如改變一個或多個物體的位姿和組成,并且保持其他特征不變。相比于其他文…

c語言題庫之序列合并

文章目錄 前言C語言題目:分析1. 合并邏輯2.圖解合并邏輯 代碼實現注意事項總結思考 前言 在編程中,我們經常遇到需要將兩個有序序列合并為一個有序序列的問題。下面,我們就來詳細探討一下如何解決這個問題,包括輸入處理、合并邏輯…

python 根據網址和關鍵詞批量下載影像

最近用到了GLASS的LAI產品,但這個產品的文件夾分得很細,我需要的影像又有8個瓦片,一個一個點擊很麻煩,于是探索了批量下載的方法 一、下載1幅 import requests import re import os import requests import re# 網頁URLurl &…

深入理解Java HashSet類及其實現原理

哈嘍,各位小伙伴們,你們好呀,我是喵手。運營社區:C站/掘金/騰訊云;歡迎大家常來逛逛 今天我要給大家分享一些自己日常學習到的一些知識點,并以文字的形式跟大家一起交流,互相學習,一…

Java中什么是多態?多態的實現原理是什么?多態在Java中的意思實現方式是什么?多態在框架設計中有什么作用應用場景?

什么是多態? 多態是面向對象編程中的一個重要概念,它允許不同類的對象對同一消息做出響應。在 Java中,多態通常體現為子類對象可以替代父類對象的特性。這意味著你可以使用父類的引用來引用子類的對象。 多態的實現原理: 多態的…

如何在 CentOS 上安裝并配置 Redis

如何在 CentOS 上安裝并配置 Redis 但是太陽,他每時每刻都是夕陽也都是旭日。當他熄滅著走下山去收盡蒼涼殘照之際,正是他在另一面燃燒著爬上山巔散烈烈朝暉之時。 ——史鐵生 環境準備 本教程將在 CentOS 7 或 CentOS 8 上進行。確保你的系統已更新到最…

Channel實現Flutter與原生平臺之間的雙向通信

文章目錄 (一)通過MessageChannel實現Flutter與原生平臺之間的雙向通信Flutter端實現MessageChannel通信步驟:Android端實現MessageChannel通信步驟: (二)通過MethodChannel實現Flutter與原生平臺之間的雙向…

uniapp/微信小程序實現加入購物車點擊添加飛到購物車動畫

1、預期效果 2、實現思路 每次點擊添加按鈕時,往該按鈕上方添加一個懸浮元素,通過位移動畫將元素移到目標位置。 1. 為每個點擊元素設置不同的class,才能通過uni.createSelectorQuery來獲取每個元素的節點信息; 2. 添加一個與…

c++:(map和set的底層簡單版本,紅黑樹和AVL樹的基礎) 二叉搜索樹(BST)底層和模擬實現

文章目錄 二叉搜索樹的概念二叉搜索樹的操作二叉搜索樹的查找find 二叉搜索樹的模擬實現構造節點insertfinderase(細節巨多,面試可能會考)a.葉子節點b.有一個孩子左孩子右孩子 c.有兩個孩子注意: erase代碼 中序遍歷 二叉搜索樹的應用k模型k模型模擬實現的總代碼 k-value模型k-…

7-Zip命令行調用命令收集(20個)

列出壓縮文件的內容: 7z l archive.7z 解壓壓縮文件到當前目錄: 7z x archive.7z 解壓壓縮文件到指定目錄: 7z x archive.7z -o"C:\path\to\extract" 創建新的壓縮文件 (添加到archive.7z): 7z a archive.7z file_to_compress 創建包含多個文件的壓縮文件: 7z a arc…