解決docker容器(java程序)內(nèi)存過(guò)大的問題
1、系統(tǒng)層面內(nèi)存排查
1 docker stats查看容器使用總內(nèi)存
通過(guò)docker stats [容器id]
命令查看內(nèi)存占用如下:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS f414a2f20364 xxx 5.84% 38.19GiB / 123.2GiB 31.00% 1.34TB / 1.5TB 1.16GB / 29.8MB 354
2 在宿主機(jī)查看容器內(nèi)存使用情況
1、通過(guò)ps -ef | grep [容器標(biāo)識(shí)]
查詢?nèi)萜鱬id
root 12683 1 0 Feb11 ? 00:01:57 /usr/bin/containerd-shim-runc-v2 -namespace moby -id f414a2f203647ceab75bb4a1be3a1d0e5578eb14b9c1780810d6416c97bbdb86 -address /run/containerd/containerd.sock
- 各列的解釋:
- UID(root): 用戶ID,表示運(yùn)行該進(jìn)程的用戶。在你的輸出中,root表示該進(jìn)程是由root用戶啟動(dòng)的。
- PID(12683): 進(jìn)程ID,系統(tǒng)中每個(gè)進(jìn)程的唯一標(biāo)識(shí)符。
- PPID(23606 和 1): 父進(jìn)程ID,PPID為1,通常表示它是由init系統(tǒng)或Docker守護(hù)進(jìn)程直接啟動(dòng)的。
- C(0): CPU使用率的簡(jiǎn)化表示,通常是進(jìn)程的調(diào)度優(yōu)先級(jí)。
- STIME(10:38 和 Feb11): 進(jìn)程啟動(dòng)時(shí)間或日期。 10:38表示當(dāng)天的時(shí)間,而Feb11表示進(jìn)程是在2月11日啟動(dòng)的。
- TTY( ?): 終端類型,表示進(jìn)程關(guān)聯(lián)的終端。pts/2表示偽終端,通常是用戶通過(guò)SSH或終端會(huì)話啟動(dòng)的。?表示沒有關(guān)聯(lián)的終端,通常是后臺(tái)進(jìn)程。
- TIME(00:00:00 和 00:01:57):進(jìn)程使用的累計(jì)CPU時(shí)間。
- CMD: 啟動(dòng)進(jìn)程的命令及其參數(shù)。
- containerd-shim介紹:
- /usr/bin/containerd-shim-runc-v2:這是可執(zhí)行文件的路徑,表示containerd的一個(gè)組件,負(fù)責(zé)管理容器的生命周期。
- -namespace moby:-namespace參數(shù)指定了容器所屬的命名空間。在Docker中,moby通常是默認(rèn)的命名空間,用于隔離不同的容器和資源。
- -id f414a2f203647ceab75bb4a1be3a1d0e5578eb14b9c1780810d6416c97bbdb86:-id參數(shù)指定了容器的完整ID。這個(gè)ID是容器的唯一標(biāo)識(shí)符,用于管理和操作容器。
- -address /run/containerd/containerd.sock: -address參數(shù)指定了與containerd守護(hù)進(jìn)程通信的Unix套接字地址。/run/containerd/containerd.sock是containerd的默認(rèn)套接字文件,用于進(jìn)程間通信。
2、通過(guò)父進(jìn)程pid找到容器內(nèi)進(jìn)程的pid: ps -ef | grep f414a2f20364
root 12683 1 0 Feb11 ? 00:01:57 /usr/bin/containerd-shim-runc-v2 -namespace moby -id f414a2f203647ceab75bb4a1be3a1d0e5578eb14b9c1780810d6416c97bbdb86 -address /run/containerd/containerd.sock root 12742 12683 3 Feb11 ? 22:02:41 java -jar xxx.jar
3、top -p [pid1,pid2]
查看真正內(nèi)存占用
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12683 root 20 0 720048 8180 2888 S 0.0 0.0 1:57.85 containerd-shim 12742 root 20 0 41.2g 27.9g 7008 S 0.0 22.6 1322:52 java
3 內(nèi)存顯示不一致的問題
通過(guò)上述步驟,發(fā)現(xiàn)docker stats
與top
所看到的內(nèi)存不一致,原因如下:
docker stats
顯示的是整個(gè)容器的內(nèi)存使用情況,包括所有進(jìn)程的內(nèi)存占用,還包括一些緩存
和緩沖區(qū)的內(nèi)存,這些在top
中是不直接顯示的。
4 排查容器的緩存占用
通過(guò)cgroup文件系統(tǒng)可以查看指定容器的內(nèi)存使用情況:
cache
:表示緩存的內(nèi)存大小rss
:表示常駐內(nèi)存大小。
1、方式1,在宿主機(jī)通過(guò)cgroup文件系統(tǒng)查看指定容器的內(nèi)存使用情況。
cat /sys/fs/cgroup/memory/docker/容器id/memory.stat cache 20683264000 rss 29628477440 rss_huge 291504128 mapped_file 942080 swap 0 ...
2、方式2,在容器內(nèi)查看訪問文件系統(tǒng)查看內(nèi)存使用情況。
cat /sys/fs/cgroup/memory/memory.stat cache 20683264000 rss 29629128704 rss_huge 291504128 mapped_file 1990656 swap 0 ...
5 查看系統(tǒng)內(nèi)存使用情況
無(wú)論在容器內(nèi)外,使用cat /proc/meminfo
命令,查看的都是當(dāng)前宿主機(jī)的內(nèi)存使用情況
cat /proc/meminfo MemTotal: 129183640 kB MemFree: 818860 kB MemAvailable: 24080828 kB Buffers: 180204 kB Cached: 23378164 kB SwapCached: 0 kB Active: 113819220 kB Inactive: 11582364 kB Active(anon): 101853876 kB Inactive(anon): 31492 kB Active(file): 11965344 kB Inactive(file): 11550872 kB Unevictable: 10448 kB ...
2、jvm層面內(nèi)存排查
1、查看堆內(nèi)存情況
1、為docker賦予權(quán)限,使得容器內(nèi)可以查看到宿主機(jī)的進(jìn)程(不推薦,因?yàn)椴话踩?br />docker run 添加--cap-add=SYS_PTRACE
參數(shù),或docker-compose添加如下參數(shù):
version: "3" services: xxx: image: xxx cap_add: - SYS_PTRACE
然后執(zhí)行jmap -heap [pid]
,查看jvm使用情況
2、使用arthas查看(推薦)
curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar
[arthas@1]$ dashboard Memory used total max usage GC heap 7276M 20714M 27305M 26.65% gc.ps_scavenge.count 9623 ps_eden_space 1174M 4067M 10203M 11.51% gc.ps_scavenge.time(ms) 1112280 ps_survivor_space 8M 8M 8M 96.63% gc.ps_marksweep.count 42 ps_old_gen 6093M 16638M 20479M 29.76% gc.ps_marksweep.time(ms) 49463 nonheap 340M 352M -1 96.49% code_cache 155M 159M 240M 64.72% metaspace 166M 173M -1 95.86% compressed_class_space 18M 19M 1024M 1.83% direct 263K 263K - 100.00% mapped 0K 0K - 0.00%
2、查看gc情況
root@f414a2f20364:/arthas# jstat -gcutil 1 1000 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 99.30 0.00 1.19 36.63 95.87 94.28 9625 1112.458 42 49.464 1161.923 99.30 0.00 1.19 36.63 95.87 94.28 9625 1112.458 42 49.464 1161.923 99.30 0.00 1.19 36.63 95.87 94.28 9625 1112.458 42 49.464 1161.923
3、查看jvm啟動(dòng)參數(shù)
添加--cap-add=SYS_PTRACE
參數(shù),執(zhí)行如下命令:
root@f414a2f20364:/arthas# jinfo 1 ... VM Flags: Non-default VM flags: -XX:CICompilerCount=12 -XX:CMSFullGCsBeforeCompaction=3 -XX:CompressedClassSpaceSize=528482304 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=2147483648 -XX:MaxHeapSize=8589934592 -XX:MaxMetaspaceSize=536870912 -XX:MaxNewSize=2863136768 -XX:MetaspaceSize=536870912 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=715653120 -XX:OldSize=1431830528 -XX:+UseCMSCompactAtFullCollection -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC Command line: -Xms2g -Xmx8g -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=3
4、查看直接內(nèi)存的使用情況
Native Memory Tracker默認(rèn)是關(guān)閉的,需要添加jvm啟動(dòng)參數(shù)查看:-XX:NativeMemoryTracking=summary
jcmd [pid] VM.native_memory summary
root@663104c83c9e:/app# jcmd 1 VM.native_memory summary 1: Native Memory Tracking: Total: reserved=10191931KB, committed=3140431KB - Java Heap (reserved=8388608KB, committed=2621952KB) (mmap: reserved=8388608KB, committed=2621952KB) - Class (reserved=1119589KB, committed=78181KB) (classes #11966) (malloc=15717KB #17876) (mmap: reserved=1103872KB, committed=62464KB) - Thread (reserved=71121KB, committed=71121KB) (thread #70) (stack: reserved=70820KB, committed=70820KB) (malloc=231KB #414) (arena=69KB #126) - Code (reserved=253980KB, committed=29992KB) (malloc=4380KB #6007) (mmap: reserved=249600KB, committed=25612KB) - GC (reserved=322636KB, committed=303188KB) (malloc=16156KB #296) (mmap: reserved=306480KB, committed=287032KB) - Compiler (reserved=205KB, committed=205KB) (malloc=63KB #668) (arena=142KB #15) - Internal (reserved=16497KB, committed=16497KB) (malloc=16465KB #16598) (mmap: reserved=32KB, committed=32KB) - Symbol (reserved=16233KB, committed=16233KB) (malloc=14211KB #139114) (arena=2022KB #1) - Native Memory Tracking (reserved=2845KB, committed=2845KB) (malloc=12KB #140) (tracking overhead=2833KB) - Arena Chunk (reserved=217KB, committed=217KB) (malloc=217KB)
3 結(jié)論
1、jvm內(nèi)存未限制
2、容器緩存占用較高
3、未限制容器內(nèi)存上限
4 內(nèi)存限制
1 限制jvm內(nèi)存
配置jvm啟動(dòng)參數(shù):
command: java -Xms2g -Xmx8g -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:NativeMemoryTracking=summary -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=3 -jar xxx.jar
以下是你提供的JVM參數(shù)的解釋:
- -Xms2g:設(shè)置JVM初始堆內(nèi)存大小為2GB,這是JVM啟動(dòng)時(shí)分配的內(nèi)存量。
- -Xmx8g:設(shè)置JVM最大堆內(nèi)存大小為8GB,這是JVM可以使用的最大內(nèi)存量。
- -XX:MaxMetaspaceSize=512m:設(shè)置元空間(Metaspace)的最大大小為512MB,元空間用于存儲(chǔ)類元數(shù)據(jù)。
- -XX:MetaspaceSize=512m: 設(shè)置元空間的初始大小為512MB,JVM會(huì)根據(jù)需要?jiǎng)討B(tài)調(diào)整元空間的大小。
- -XX:NativeMemoryTracking=summary:?jiǎn)⒂帽镜貎?nèi)存跟蹤(Native Memory Tracking, NMT),并設(shè)置為摘要模式,NMT用于監(jiān)控JVM的本地內(nèi)存使用,幫助診斷內(nèi)存泄漏和優(yōu)化內(nèi)存使用。
- -XX:+HeapDumpOnOutOfMemoryError:?jiǎn)⒂么诉x項(xiàng)會(huì)在發(fā)生內(nèi)存溢出錯(cuò)誤時(shí)生成堆轉(zhuǎn)儲(chǔ)文件,便于后續(xù)分析和調(diào)試。
- -XX:+UseCMSCompactAtFullCollection:在使用CMS(Concurrent Mark-Sweep)垃圾收集器時(shí),啟用在Full GC后進(jìn)行內(nèi)存壓縮,以減少內(nèi)存碎片。
- -XX:CMSFullGCsBeforeCompaction=3: 設(shè)置在進(jìn)行3次Full GC后進(jìn)行一次內(nèi)存壓縮。這與
UseCMSCompactAtFullCollection
結(jié)合使用,幫助減少內(nèi)存碎片。
2 清理宿主機(jī)cache
將所有未寫的系統(tǒng)緩沖區(qū)寫到磁盤中,包含已修改的i-node、已延遲的塊I/O和讀寫映射文件,同時(shí)清除pagecache和slab分配器中的緩存對(duì)象。
sync; echo 3 > /proc/sys/vm/drop_caches
3 限制容器自身內(nèi)存使用
version: "3" services: xxx: deploy: resources: limits: memory: 10G
到此這篇關(guān)于解決docker容器(java程序)內(nèi)存占用過(guò)大的問題的文章就介紹到這了,更多相關(guān)docker內(nèi)存占用過(guò)大內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Docker Buildx構(gòu)建多平臺(tái)鏡像的實(shí)現(xiàn)
本文主要介紹了Docker Buildx構(gòu)建多平臺(tái)鏡像的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07docker安裝RocketMQ的實(shí)現(xiàn)(附填坑經(jīng)驗(yàn)connect to failed)
本文主要介紹了docker安裝RocketMQ(附填坑經(jīng)驗(yàn)connect to failed)2024-06-06docker實(shí)現(xiàn)重新打tag并刪除原tag的鏡像
這篇文章主要介紹了docker實(shí)現(xiàn)重新打tag并刪除原tag的鏡像,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11使用Golang玩轉(zhuǎn)Docker API的實(shí)踐
這篇文章主要介紹了使用Golang玩轉(zhuǎn)Docker API的實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Docker 搭建lamp應(yīng)用實(shí)例詳解
這篇文章主要介紹了Docker 搭建lamp應(yīng)用實(shí)例詳解的相關(guān)資料,這里對(duì)搭建 LAMP的步驟做了詳細(xì)介紹,需要的朋友可以參考下2016-11-11docker安裝jiacrontab可視化任務(wù)管理工具詳解
jiacrontab 是基于 Web 的可視化定時(shí)任務(wù)管理工具,由 server(調(diào)度多 client)和 client(執(zhí)行腳本)通過(guò) RPC 通信構(gòu)成,支持超時(shí)處理、并發(fā)控制、依賴管理及兼容 Linux crontab 格式,便于多服務(wù)器統(tǒng)一管理2025-07-07Docker文件映射實(shí)現(xiàn)主機(jī)與容器間目錄的雙向映射
本地文件系統(tǒng)和容器中的文件系統(tǒng)之間的交互是一項(xiàng)必不可少的功能,本文主要介紹了Docker文件映射實(shí)現(xiàn)主機(jī)與容器間目錄的雙向映射,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03