![](http://img.inpai.com.cn/2023/0410/20230410091623448.jpg)
背景信息
(資料圖片僅供參考)
當(dāng)您的業(yè)務(wù)是使用Java開(kāi)發(fā),且設(shè)置的JVM堆空間過(guò)小時(shí),程序會(huì)出現(xiàn)系統(tǒng)內(nèi)存不足OOM(Out of Memory)的問(wèn)題。事件中心的OOM事件是指系統(tǒng)內(nèi)存不足時(shí),觸發(fā)了Linux的內(nèi)存回收(OOM Killer)機(jī)制,此時(shí)系統(tǒng)會(huì)終止內(nèi)存占用較多的進(jìn)程以保證系統(tǒng)的正常運(yùn)行。特別是在容器環(huán)境下,不合理的JVM堆參數(shù)設(shè)置會(huì)導(dǎo)致各種異?,F(xiàn)象產(chǎn)生,例如應(yīng)用堆大小還未到達(dá)JVM設(shè)置的堆閾值或應(yīng)用的規(guī)格限制,就因?yàn)镺OM導(dǎo)致重啟等。
通過(guò)-XX:MaxRAMPercentage限制堆大?。?u>推薦)
在容器環(huán)境下,Java只能獲取服務(wù)器的配置,無(wú)法感知容器內(nèi)存限制。您可以通過(guò)設(shè)置-Xmx來(lái)限制JVM堆大小,但該方式存在以下問(wèn)題:
當(dāng)規(guī)格大小調(diào)整后,需要重新設(shè)置堆大小參數(shù)。
當(dāng)參數(shù)設(shè)置不合理時(shí),會(huì)出現(xiàn)應(yīng)用堆大小未達(dá)到閾值但容器OOM被強(qiáng)制關(guān)閉的情況。
說(shuō)明
「應(yīng)用程序出現(xiàn)OOM問(wèn)題時(shí),會(huì)觸發(fā)Linux內(nèi)核的OOM Killer機(jī)制。該機(jī)制能夠監(jiān)控占用過(guò)大內(nèi)存,尤其是瞬間消耗大量?jī)?nèi)存的進(jìn)程,然后它會(huì)強(qiáng)制關(guān)閉某項(xiàng)進(jìn)程以騰出內(nèi)存留給系統(tǒng),避免系統(tǒng)立刻崩潰?!?/strong>
推薦的JVM參數(shù)設(shè)置
-XX:+UseContainerSupport-XX:InitialRAMPercentage=70.0-XX:MaxRAMPercentage=70.0-XX:MinRAMPercentage=70.0-XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date"+%s").log-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date"+%s").hprof
參數(shù) | 說(shuō)明 |
-XX:+UseContainerSupport | 使用容器內(nèi)存。允許JVM從主機(jī)讀取cgroup限制,例如可用的CPU和RAM,并進(jìn)行相應(yīng)的配置。當(dāng)容器超過(guò)內(nèi)存限制時(shí),會(huì)拋出OOM異常,而不是強(qiáng)制關(guān)閉容器。 |
-XX:InitialRAMPercentage | 設(shè)置JVM使用容器內(nèi)存的初始百分比。建議與-XX:MaxRAMPercentage保持一致,推薦設(shè)置為70.0。 |
-XX:MaxRAMPercentage | 設(shè)置JVM使用容器內(nèi)存的最大百分比。由于存在系統(tǒng)組件開(kāi)銷(xiāo),建議最大不超過(guò)75.0,推薦設(shè)置為70.0。 |
-XX:+PrintGCDetails | 輸出GC詳細(xì)信息。 |
-XX:+PrintGCDateStamps | 輸出GC時(shí)間戳。日期形式,例如2019-12-24T2159.234+0800。 |
-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date "+%s").log | GC日志文件路徑。需保證Log文件所在容器路徑已存在,建議您將該容器路徑掛載到NAS目錄或收集到SLS,以便自動(dòng)創(chuàng)建目錄以及實(shí)現(xiàn)日志的持久化存儲(chǔ)。 |
-XX:+HeapDumpOnOutOfMemoryError | JVM發(fā)生OOM時(shí),自動(dòng)生成DUMP文件。 |
-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date "+%s").hprof | DUMP文件路徑。需保證DUMP文件所在容器路徑已存在,建議您將該容器路徑掛載到NAS目錄,以便自動(dòng)創(chuàng)建目錄以及實(shí)現(xiàn)日志的持久化存儲(chǔ)。 |
?
說(shuō)明
使用-XX:+UseContainerSupport參數(shù)需JDK 8u191+、JDK 10及以上版本。JDK 11版本下日志相關(guān)的參數(shù)-XX:+PrintGCDetails、-XX:+PrintGCDateStamps、-Xloggc:LOG_PATH/gc.log代替。Dragonwell 11暫不支持${POD_IP} 變量。如果您沒(méi)有將/home/admin/nas容器路徑掛載到NAS目錄,則必須保證該目錄在應(yīng)用啟動(dòng)前已存在,否則將不會(huì)產(chǎn)生日志文件。
?
常見(jiàn)問(wèn)題
容器出現(xiàn)137退出碼的含義是什么?
當(dāng)容器使用內(nèi)存超過(guò)限制時(shí),會(huì)出現(xiàn)容器OOM,導(dǎo)致容器被強(qiáng)制關(guān)閉。此時(shí)業(yè)務(wù)應(yīng)用內(nèi)存可能并未達(dá)到JVM堆大小上限,所以不會(huì)產(chǎn)生dump日志。建議您調(diào)小JVM堆大小的上限,為容器內(nèi)其他系統(tǒng)組件預(yù)留足夠多的內(nèi)存空間。
為什么發(fā)生OOM卻沒(méi)有生成dump文件?
當(dāng)發(fā)生OOM Killer時(shí),并不一定會(huì)發(fā)生JVM OOM,所以不會(huì)生成dump文件。您可以采取以下方式來(lái)避免這種情況。
如果是Java應(yīng)用,可以適當(dāng)調(diào)小JVM的堆內(nèi)存大小。具體配置,請(qǐng)參見(jiàn)本文。
如果是非Java應(yīng)用,可以調(diào)整實(shí)例規(guī)格,保證充裕的內(nèi)存資源。
堆大小和規(guī)格內(nèi)存的參數(shù)值可以相同嗎?
不可以。
因?yàn)橄到y(tǒng)自身組件存在內(nèi)存開(kāi)銷(xiāo),所以不能將JVM堆大小設(shè)置為和規(guī)格內(nèi)存大小相同的數(shù)值,需要為這些系統(tǒng)組件預(yù)留足夠的內(nèi)存空間。
在JDK 8版本下設(shè)置-XX:MaxRAMPercentage值為整數(shù)時(shí)報(bào)錯(cuò)怎么處理?
這是JDK 8的一個(gè)Bug。
具體信息,請(qǐng)參見(jiàn)Java Bug Database。例如,在JDK 8u191版本下,設(shè)置-XX:MaxRAMPercentage=70,此時(shí)JVM會(huì)啟動(dòng)報(bào)錯(cuò)。
解決方案如下:
方式一:設(shè)置-XX:MaxRAMPercentage為70.0。說(shuō)明 如果您使用了-XX:InitialRAMPercentage或-XX:MinRAMPercentage,參數(shù)值同樣不可設(shè)置為整數(shù)。
方式二:升級(jí)JDK版本至JDK 10及以上版本。
為什么JVM參數(shù)設(shè)置了6 GB,但是內(nèi)存使用率卻很低?
雖然JVM參數(shù)已設(shè)置-Xms6g -Xmx6g,但是操作系統(tǒng)不會(huì)馬上分配6 GB的物理內(nèi)存,需要實(shí)際使用后才分配。因此,內(nèi)存使用率在應(yīng)用啟動(dòng)的時(shí)候,會(huì)相對(duì)較低,后續(xù)會(huì)出現(xiàn)攀爬現(xiàn)象。
調(diào)優(yōu)堆棧內(nèi)存
表 1. 堆棧大小典型配置參數(shù)
調(diào)優(yōu)回收器GC
表 2. 吞吐量?jī)?yōu)先的GC典型配置參數(shù)
表 3. 響應(yīng)時(shí)間優(yōu)先的GC典型配置參數(shù)
表 4. 用于輔助的GC典型配置參數(shù)
審核編輯:湯梓紅標(biāo)簽: