日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
解讀Java云原生實踐中的內(nèi)存問題

解讀 Java 云原生實踐中的內(nèi)存問題

作者:風(fēng)敬(謝文欣) 2023-01-14 22:59:34

云計算

云原生 對外提供服務(wù)的業(yè)務(wù)往往會帶來更活躍的內(nèi)存分配動作,比如創(chuàng)建新的對象、開啟執(zhí)行線程,這些操作都需要開辟內(nèi)存空間,所以線上業(yè)務(wù)往往耗費(fèi)更多內(nèi)存。并且越是流量高峰期,耗費(fèi)的內(nèi)存會更多。所以為了保證服務(wù)質(zhì)量,需要依據(jù)自身業(yè)務(wù)流量,對應(yīng)用內(nèi)存配置進(jìn)行相應(yīng)擴(kuò)容。

成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、黃梅網(wǎng)絡(luò)推廣、小程序制作、黃梅網(wǎng)絡(luò)營銷、黃梅企業(yè)策劃、黃梅品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供黃梅建站搭建服務(wù),24小時服務(wù)熱線:028-86922220,官方網(wǎng)址:www.cdcxhl.com

?Java 憑借著自身活躍的開源社區(qū)和完善的生態(tài)優(yōu)勢,在過去的二十幾年一直是最受歡迎的編程語言之一。步入云原生時代,蓬勃發(fā)展的云原生技術(shù)釋放云計算紅利,推動業(yè)務(wù)進(jìn)行云原生化改造,加速企業(yè)數(shù)字化轉(zhuǎn)型。

然而 Java 的云原生轉(zhuǎn)型之路面臨著巨大的挑戰(zhàn),Java 的運(yùn)行機(jī)制和云原生特性存在著諸多矛盾。企業(yè)借助云原生技術(shù)進(jìn)行深層次成本優(yōu)化,資源成本管理被上升到前所未有的高度。公有云上資源按量收費(fèi),用戶對資源用量十分敏感。在內(nèi)存使用方面,基于 Java 虛擬機(jī)的執(zhí)行機(jī)制使得任何 Java 程序都會有固定的基礎(chǔ)內(nèi)存開銷,相比 C++/Golang 等原生語言,Java 應(yīng)用占用的內(nèi)存巨大,被稱為“內(nèi)存吞噬者”,因此 Java 應(yīng)用上云更加昂貴。并且應(yīng)用集成到云上之后系統(tǒng)復(fù)雜度增加,普通用戶對云上 Java 應(yīng)用內(nèi)存沒有清晰的認(rèn)識,不知道如何為應(yīng)用合理配置內(nèi)存,出現(xiàn) OOM 問題時也很難排障,遇到了許多問題。

為什么堆內(nèi)存未超過 Xmx 卻發(fā)生了 OOM?怎么理解操作系統(tǒng)和JVM的內(nèi)存關(guān)系?為什么程序占用的內(nèi)存比 Xmx 大不少,內(nèi)存都用在哪兒了?為什么線上容器內(nèi)的程序內(nèi)存需求更大?本文將 EDAS 用戶在 Java 應(yīng)用云原生化演進(jìn)實踐中遇到的這些問題進(jìn)行了抽絲剝繭的分析,并給出云原生 Java 應(yīng)用內(nèi)存的配置建議。

一、背景知識

K8s 應(yīng)用的資源配置?

云原生架構(gòu)以 K8s 為基石,應(yīng)用在 K8s 上部署,以容器組的形態(tài)運(yùn)行。K8s 的資源模型有兩個定義,資源請求(request)和資源限制(limit),K8s 保障容器擁有 request數(shù)量的資源,但不允許使用超過limit數(shù)量的資源。以如下的內(nèi)存配置為例,容器至少能獲得 1024Mi 的內(nèi)存資源,但不允許超過 4096Mi,一旦內(nèi)存使用超限,該容器將發(fā)生OOM,而后被 K8s 控制器重啟。 

spec:
containers:
- name: edas
image: alibaba/edas
resources:
requests:
memory: "1024Mi"
limits:
memory: "4096Mi"
command: ["java", "-jar", "edas.jar"]

容器 OOM?

對于容器的 OOM 機(jī)制,首先需要來復(fù)習(xí)一下容器的概念。當(dāng)我們談到容器的時候,會說這是一種沙盒技術(shù),容器作為一個沙盒,內(nèi)部是相對獨立的,并且是有邊界有大小的。容器內(nèi)獨立的運(yùn)行環(huán)境通過 Linux的Namespace 機(jī)制實現(xiàn),對容器內(nèi) PID、Mount、UTS、IPD、Network 等 Namespace 進(jìn)行了障眼法處理,使得容器內(nèi)看不到宿主機(jī) Namespace 也看不到其他容器的 Namespace;而所謂容器的邊界和大小,是指要對容器使用 CPU、內(nèi)存、IO 等資源進(jìn)行約束,不然單個容器占用資源過多可能導(dǎo)致其他容器運(yùn)行緩慢或者異常。Cgroup 是 Linux 內(nèi)核提供的一種可以限制單個進(jìn)程或者多個進(jìn)程所使用資源的機(jī)制,也是實現(xiàn)容器資源約束的核心技術(shù)。容器在操作系統(tǒng)看來只不過是一種特殊進(jìn)程,該進(jìn)程對資源的使用受 Cgroup 的約束。當(dāng)進(jìn)程使用的內(nèi)存量超過 Cgroup 的限制量,就會被系統(tǒng) OOM Killer 無情地殺死。

所以,所謂的容器 OOM,實質(zhì)是運(yùn)行在Linux系統(tǒng)上的容器進(jìn)程發(fā)生了 OOM。Cgroup 并不是一種晦澀難懂的技術(shù),Linux 將其實現(xiàn)為了文件系統(tǒng),這很符合 Unix 一切皆文件的哲學(xué)。對于 Cgroup V1 版本,我們可以直接在容器內(nèi)的 /sys/fs/cgroup/ 目錄下查看當(dāng)前容器的 Cgroup 配置。

對于容器內(nèi)存來說,memory.limit_in_bytes 和 memory.usage_in_bytes 是內(nèi)存控制組中最重要的兩個參數(shù),前者標(biāo)識了當(dāng)前容器進(jìn)程組可使用內(nèi)存的最大值,后者是當(dāng)前容器進(jìn)程組實際使用的內(nèi)存總和。一般來說,使用值和最大值越接近,OOM 的風(fēng)險越高。

# 當(dāng)前容器內(nèi)存限制量
$ cat /sys/fs/cgroup/memory/memory.limit_in_bytes
4294967296
# 當(dāng)前容器內(nèi)存實際用量
$ cat /sys/fs/cgroup/memory/memory.usage_in_bytes
39215104

JVM OOM?

說到 OOM,Java 開發(fā)者更熟悉的是 JVM OOM,當(dāng) JVM 因為沒有足夠的內(nèi)存來為對象分配空間并且垃圾回收器也已經(jīng)沒有空間可回收時,將會拋出 java.lang.OutOfMemoryError。按照 JVM 規(guī)范,除了程序計數(shù)器不會拋出 OOM 外,其他各個內(nèi)存區(qū)域都可能會拋出 OOM。最常見的 JVM OOM 情況有幾種:

  • java.lang.OutOfMemoryError:Java heap space 堆內(nèi)存溢出。當(dāng)堆內(nèi)存 (Heap Space) 沒有足夠空間存放新創(chuàng)建的對象時,就會拋出該錯誤。一般由于內(nèi)存泄露或者堆的大小設(shè)置不當(dāng)引起。對于內(nèi)存泄露,需要通過內(nèi)存監(jiān)控軟件查找程序中的泄露代碼,而堆大小可以通過-Xms,-Xmx等參數(shù)修改。
  • java.lang.OutOfMemoryError:PermGen space / Metaspace 永久代/元空間溢出。永久代存儲對象包括class信息和常量,JDK 1.8 使用 Metaspace 替換了永久代(Permanent Generation)。通常因為加載的 class 數(shù)目太多或體積太大,導(dǎo)致拋出該錯誤??梢酝ㄟ^修改 -XX:MaxPermSize 或者 -XX:MaxMetaspaceSize 啟動參數(shù), 調(diào)大永久代/元空間大小。
  • java.lang.OutOfMemoryError:Unable to create new native thread 無法創(chuàng)建新線程。每個 Java 線程都需要占用一定的內(nèi)存空間, 當(dāng) JVM 向底層操作系統(tǒng)請求創(chuàng)建一個新的 native 線程時, 如果沒有足夠的資源分配就會報此類錯誤??赡茉蚴?native 內(nèi)存不足、線程泄露導(dǎo)致線程數(shù)超過操作系統(tǒng)最大線程數(shù) ulimit 限制或是線程數(shù)超過 kernel.pid_max。需要根據(jù)情況進(jìn)行資源升配、限制線程池大小、減少線程棧大小等操作。

二、為什么堆內(nèi)存未超過 Xmx 卻發(fā)生了 OOM?

相信很多人都遇到過這一場景,在 K8s 部署的 Java 應(yīng)用經(jīng)常重啟,查看容器退出狀態(tài)為exit code 137 reason: OOM Killed 各方信息都指向明顯的 OOM,然而 JVM 監(jiān)控數(shù)據(jù)顯示堆內(nèi)存用量并未超過最大堆內(nèi)存限制Xmx,并且配置了 OOM 自動 heapdump 參數(shù)之后,發(fā)生 OOM 時卻沒有產(chǎn)生 dump 文件。

根據(jù)上面的背景知識介紹,容器內(nèi)的 Java 應(yīng)用可能會發(fā)生兩種類型的 OOM 異常,一種是 JVM OOM,一種是容器 OOM。JVM 的 OOM 是 JVM 內(nèi)存區(qū)域空間不足導(dǎo)致的錯誤,JVM 主動拋出錯誤并退出進(jìn)程,通過觀測數(shù)據(jù)可以看到內(nèi)存用量超限,并且 JVM 會留下相應(yīng)的錯誤記錄。而容器的 OOM 是系統(tǒng)行為,整個容器進(jìn)程組使用的內(nèi)存超過 Cgroup 限制,被系統(tǒng) OOM Killer 殺死,在系統(tǒng)日志和 K8s 事件中會留下相關(guān)記錄。

總的來說,Java程序內(nèi)存使用同時受到來自 JVM 和 Cgroup 的限制,其中 Java 堆內(nèi)存受限于 Xmx 參數(shù),超限后發(fā)生 JVM OOM;整個進(jìn)程內(nèi)存受限于容器內(nèi)存limit值,超限后發(fā)生容器 OOM。需要結(jié)合觀測數(shù)據(jù)、JVM 錯誤記錄、系統(tǒng)日志和 K8s 事件對 OOM 進(jìn)行區(qū)分、排障,并按需進(jìn)行配置調(diào)整。

三、怎么理解操作系統(tǒng)和 JVM 的內(nèi)存關(guān)系?

上文說到 Java 容器 OOM 實質(zhì)是 Java 進(jìn)程使用的內(nèi)存超過 Cgroup 限制,被操作系統(tǒng)的 OOM Killer 殺死。那在操作系統(tǒng)的視角里,如何看待 Java 進(jìn)程的內(nèi)存?操作系統(tǒng)和 JVM 都有各自的內(nèi)存模型,二者是如何映射的?對于探究 Java 進(jìn)程的 OOM 問題,理解 JVM 和操作系統(tǒng)之間的內(nèi)存關(guān)系非常重要。

以最常用的 OpenJDK 為例,JVM 本質(zhì)上是運(yùn)行在操作系統(tǒng)上的一個 C++ 進(jìn)程,因此其內(nèi)存模型也有 Linux 進(jìn)程的一般特點。Linux 進(jìn)程的虛擬地址空間分為內(nèi)核空間和用戶空間,用戶空間又細(xì)分為很多個段,此處選取幾個和本文討論相關(guān)度高的幾個段,描述 JVM 內(nèi)存與進(jìn)程內(nèi)存的映射關(guān)系。

  • 代碼段。一般指程序代碼在內(nèi)存中的映射,這里特別指出是 JVM 自身的代碼,而不是Java代碼。
  • 數(shù)據(jù)段。在程序運(yùn)行初已經(jīng)對變量進(jìn)行初始化的數(shù)據(jù),此處是 JVM 自身的數(shù)據(jù)。
  • 堆空間。運(yùn)行時堆是 Java 進(jìn)程和普通進(jìn)程區(qū)別最大的一個內(nèi)存段。Linux 進(jìn)程內(nèi)存模型里的堆是為進(jìn)程在運(yùn)行時動態(tài)分配的對象提供內(nèi)存空間,而幾乎所有JVM內(nèi)存模型里的東西,都是 JVM 這個進(jìn)程在運(yùn)行時新建出來的對象。而 JVM 內(nèi)存模型中的 Java 堆,只不過是 JVM 在其進(jìn)程堆空間上建立的一段邏輯空間。
  • ??臻g。存放進(jìn)程的運(yùn)行棧,此處并不是 JVM 內(nèi)存模型中的線程棧,而是操作系統(tǒng)運(yùn)行 JVM 本身需要留存的一些運(yùn)行數(shù)據(jù)。

如上所述,堆空間作為 Linux 進(jìn)程內(nèi)存布局和 JVM 內(nèi)存布局都有的概念,是最容易混淆也是差別最大的一個概念。Java 堆相較于 Linux 進(jìn)程的堆,范圍更小,是 JVM 在其進(jìn)程堆空間上建立的一段邏輯空間,而進(jìn)程堆空間還包含支撐 JVM 虛擬機(jī)運(yùn)行的內(nèi)存數(shù)據(jù),例如 Java 線程堆棧、代碼緩存、GC 和編譯器數(shù)據(jù)等。

四、為什么程序占用的內(nèi)存比 Xmx 大不少,內(nèi)存都用在哪了?

在 Java 開發(fā)者看來,Java 代碼運(yùn)行中開辟的對象都放在 Java 堆中,所以很多人會將 Java 堆內(nèi)存等同于 Java 進(jìn)程內(nèi)存,將 Java 堆內(nèi)存限制參數(shù)Xmx當(dāng)作進(jìn)程內(nèi)存限制參數(shù)使用,并且把容器內(nèi)存限制也設(shè)置為 Xmx 一樣大小,然后悲催地發(fā)現(xiàn)容器被 OOM 了。

實質(zhì)上除了大家所熟悉的堆內(nèi)存(Heap),JVM 還有所謂的非堆內(nèi)存(Non-Heap),除去 JVM 管理的內(nèi)存,還有繞過 JVM 直接開辟的本地內(nèi)存。Java 進(jìn)程的內(nèi)存占用情況可以簡略地總結(jié)為下圖:

JDK8 引入了 Native Memory Tracking (NMT)特性,可以追蹤 JVM 的內(nèi)部內(nèi)存使用。默認(rèn)情況下,NMT 是關(guān)閉狀態(tài),使用 JVM 參數(shù)開啟:-XX:NativeMemoryTracking=[off | summary | detail]

$ java -Xms300m -Xmx300m -XX:+UseG1GC -XX:NativeMemoryTracking=summary -jar app.jar

此處限制最大堆內(nèi)存為 300M,使用 G1 作為 GC 算法,開啟 NMT 追蹤進(jìn)程的內(nèi)存使用情況。

注意:啟用 NMT 會導(dǎo)致 5% -10% 的性能開銷。

開啟 NMT 后,可以使用 jcmd 命令打印 JVM 內(nèi)存的占用情況。此處僅查看內(nèi)存摘要信息,設(shè)置單位為 MB。

$ jcmd  VM.native_memory summary scale=MB

JVM 總內(nèi)存

Native Memory Tracking:
Total: reserved=1764MB, committed=534MB

NMT 報告顯示進(jìn)程當(dāng)前保留內(nèi)存為 1764MB,已提交內(nèi)存為 534MB,遠(yuǎn)遠(yuǎn)高于最大堆內(nèi)存 300M。保留指為進(jìn)程開辟一段連續(xù)的虛擬地址內(nèi)存,可以理解為進(jìn)程可能使用的內(nèi)存量;提交指將虛擬地址與物理內(nèi)存進(jìn)行映射,可以理解為進(jìn)程當(dāng)前占用的內(nèi)存量。

需要特別說明的是,NMT 所統(tǒng)計的內(nèi)存與操作系統(tǒng)統(tǒng)計的內(nèi)存有所差異,Linux 在分配內(nèi)存時遵循 lazy allocation 機(jī)制,只有在進(jìn)程真正訪問內(nèi)存頁時才將其換入物理內(nèi)存中,所以使用 top 命令看到的進(jìn)程物理內(nèi)存占用量與 NMT 報告中看到的有差別。此處只用 NMT 說明 JVM 視角下內(nèi)存的占用情況。

Java Heap

Java Heap (reserved=300MB, committed=300MB)    (mmap: reserved=300MB, committed=300MB)

Java 堆內(nèi)存如設(shè)置的一樣,實際開辟了 300M 的內(nèi)存空間。

Metaspace

Class (reserved=1078MB, committed=61MB)      (classes #11183)      (malloc=2MB #19375)       (mmap: reserved=1076MB, committed=60MB)

加載的類被存儲在 Metaspace,此處元空間加載了 11183 個類,保留了近 1G,提交了 61M。

加載的類越多,使用的元空間就越多。元空間大小受限于-XX:MaxMetaspaceSize(默認(rèn)無限制)和 -XX:CompressedClassSpaceSize(默認(rèn) 1G)。

Thread

Thread (reserved=60MB, committed=60MB)       (thread #61)       (stack: reserved=60MB, committed=60MB)

JVM 線程堆棧也需要占據(jù)一定空間。此處 61 個線程占用了 60M 空間,每個線程堆棧默認(rèn)約為 1M。堆棧大小由 -Xss 參數(shù)控制。

Code Cache

Code (reserved=250MB, committed=36MB)     (malloc=6MB #9546)      (mmap: reserved=244MB, committed=30MB)

代碼緩存區(qū)主要用來保存 JIT 即時編譯器編譯后的代碼和 Native 方法,目前緩存了 36M 的代碼。代碼緩存區(qū)可以通過 -XX:ReservedCodeCacheSize 參數(shù)進(jìn)行容量設(shè)置。

GC

GC (reserved=47MB, committed=47MB)
(malloc=4MB #11696)
(mmap: reserved=43MB, committed=43MB)

GC 垃圾收集器也需要一些內(nèi)存空間支撐 GC 操作,GC 占用的空間與具體選用的 GC 算法有關(guān),此處的 GC 算法使用了 47M。在其他配置相同的情況下,換用 SerialGC:

GC (reserved=1MB, committed=1MB)
(mmap: reserved=1MB, committed=1MB)

可以看到 SerialGC 算法僅使用 1M 內(nèi)存。這是因為 SerialGC 是一種簡單的串行算法,涉及數(shù)據(jù)結(jié)構(gòu)簡單,計算數(shù)據(jù)量小,所以內(nèi)存占用也小。但是簡單的 GC 算法可能會帶來性能的下降,需要平衡性能和內(nèi)存表現(xiàn)進(jìn)行選擇。

Symbol

Symbol (reserved=15MB, committed=15MB)
(malloc=11MB #113566)
(arena=3MB #1)

JVM 的 Symbol 包含符號表和字符串表,此處占用 15M。

非 JVM 內(nèi)存

NMT 只能統(tǒng)計 JVM 內(nèi)部的內(nèi)存情況,還有一部分內(nèi)存不由JVM管理。除了 JVM 托管的內(nèi)存之外,程序也可以顯式地請求堆外內(nèi)存 ByteBuffer.allocateDirect,這部分內(nèi)存受限于 -XX:MaxDirectMemorySize 參數(shù)(默認(rèn)等于-Xmx)。System.loadLibrary 所加載的 JNI 模塊也可以不受 JVM 控制地申請堆外內(nèi)存。

綜上,其實并沒有一個能準(zhǔn)確估量 Java 進(jìn)程內(nèi)存用量的模型,只能夠盡可能多地考慮到各種因素。其中有一些內(nèi)存區(qū)域能通過 JVM 參數(shù)進(jìn)行容量限制,例如代碼緩存、元空間等,但有些內(nèi)存區(qū)域不受 JVM 控制,而與具體應(yīng)用的代碼有關(guān)。

Total memory = Heap + Code Cache + Metaspace + Thread stacks + 
Symbol + GC + Direct buffers + JNI + ...

五、為什么線上容器比本地測試內(nèi)存需求更大?

經(jīng)常有用戶反饋,為什么相同的一份代碼,在線上容器里跑總是要比本地跑更耗內(nèi)存,甚至出現(xiàn) OOM。可能的情況的情況有如下幾種:

沒有使用容器感知的 JVM 版本?

在一般的物理機(jī)或虛擬機(jī)上,當(dāng)未設(shè)置 -Xmx 參數(shù)時,JVM 會從常見位置(例如,Linux 中的 /proc目錄下)查找其可以使用的最大內(nèi)存量,然后按照主機(jī)最大內(nèi)存的 1/4 作為默認(rèn)的 JVM 最大堆內(nèi)存量。而早期的 JVM 版本并未對容器進(jìn)行適配,當(dāng)運(yùn)行在容器中時,仍然按照主機(jī)內(nèi)存的 1/4 設(shè)置 JVM最 大堆,而一般集群節(jié)點的主機(jī)內(nèi)存比本地開發(fā)機(jī)大得多,容器內(nèi)的 Java 進(jìn)程堆空間開得大,自然更耗內(nèi)存。同時在容器中又受到 Cgroup 資源限制,當(dāng)容器進(jìn)程組內(nèi)存使用量超過 Cgroup 限制時,便會被 OOM。為此,8u191 之后的 OpenJDK 引入了默認(rèn)開啟的 UseContainerSupport 參數(shù),使得容器內(nèi)的 JVM 能感知容器內(nèi)存限制,按照 Cgroup 內(nèi)存限制量的 1/4 設(shè)置最大堆內(nèi)存量。

線上業(yè)務(wù)耗費(fèi)更多內(nèi)存

對外提供服務(wù)的業(yè)務(wù)往往會帶來更活躍的內(nèi)存分配動作,比如創(chuàng)建新的對象、開啟執(zhí)行線程,這些操作都需要開辟內(nèi)存空間,所以線上業(yè)務(wù)往往耗費(fèi)更多內(nèi)存。耗費(fèi)的內(nèi)存會更多。所以為了保證服務(wù)質(zhì)量,需要依據(jù)自身業(yè)務(wù)流量,對應(yīng)用內(nèi)存配置進(jìn)行相應(yīng)擴(kuò)容。

六、云原生 Java 應(yīng)用內(nèi)存的配置建議

  1. 使用容器感知的 JDK 版本。對于使用 Cgroup V1 的集群,需要升級至 8u191+、Java 9、Java 10 以及更高版本;對于使用 Cgroup V2 的集群,需要升級至 8u372+ 或 Java 15 及更高版本。
  2. 使用 NativeMemoryTracking(NMT) 了解應(yīng)用的 JVM 內(nèi)存用量。NMT 能夠追蹤 JVM 的內(nèi)存使用情況,在測試階段可以使用 NMT 了解程序JVM使用內(nèi)存的大致分布情況,作為內(nèi)存容量配置的參考依據(jù)。JVM 參數(shù) -XX:NativeMemoryTracking 用于啟用 NMT,開啟 NMT 后,可以使用 jcmd 命令打印 JVM 內(nèi)存的占用情況。
  3. 根據(jù) Java 程序內(nèi)存使用量設(shè)置容器內(nèi)存 limit。容器 Cgroup 內(nèi)存限制值來源于對容器設(shè)置的內(nèi)存 limit 值,當(dāng)容器進(jìn)程使用的內(nèi)存量超過 limit,就會發(fā)生容器 OOM。為了程序在正常運(yùn)行或業(yè)務(wù)波動時發(fā)生 OOM,應(yīng)該按照 Java 進(jìn)程使用的內(nèi)存量上浮 20%~30% 設(shè)置容器內(nèi)存 limit。如果初次運(yùn)行的程序,并不了解其實際內(nèi)存使用量,可以先設(shè)置一個較大的 limit 讓程序運(yùn)行一段時間,按照觀測到的進(jìn)程內(nèi)存量對容器內(nèi)存 limit 進(jìn)行調(diào)整。
  4. OOM 時自動 dump 內(nèi)存快照,并為 dump 文件配置持久化存儲,比如使用 PVC 掛載到 hostPath、OSS 或 NAS,盡可能保留現(xiàn)場數(shù)據(jù),支撐后續(xù)的故障排查。?


本文名稱:解讀Java云原生實踐中的內(nèi)存問題
本文來源:http://www.dlmjj.cn/article/djcjoch.html