對Docker-java項(xiàng)目進(jìn)行jvm調(diào)優(yōu)-內(nèi)存方式
1. 分析內(nèi)存使用情況
1.1 進(jìn)入docker容器
# 查看容器列表 docker ps # 根據(jù)容器name或id進(jìn)入容器命令行終端 docker exec -it <container_name> bash
1.2 通過jps查看當(dāng)前java進(jìn)程列表
三種不同詳細(xì)程度的進(jìn)程列表(主要是獲取java進(jìn)程的lvmid)
root@21e4300860c8:/# jps 1 jar 79 Jps root@21e4300860c8:/# jps -l 1 /knx-organization-service-exec.jar 127 sun.tools.jps.Jps root@21e4300860c8:/# jps -lv 1 /knx-organization-service-exec.jar -Xmx512m -Xms512m -Dspring.profiles.active=dev,jiewli -Djasypt.encryptor.password= -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=18000 139 sun.tools.jps.Jps -Dapplication.home=/usr/lib/jvm/java-8-openjdk-amd64 -Xms8m
1.3 通過jstat -gccapacity統(tǒng)計(jì)java進(jìn)程的內(nèi)存池容量
root@21e4300860c8:/# jstat -gccapacity -h 20 1 250 NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4 174592.0 174592.0 174592.0 7680.0 8704.0 157184.0 349696.0 349696.0 349696.0 349696.0 0.0 1136640.0 98280.0 0.0 1048576.0 11904.0 46 4
說明:
- 新生代空間由
Survivor0
、Survivor1
、Eden
(幸存者空間0、幸存者空間1、伊甸園)三部分組成 OGC = sum(all OC)
,目前老年代只有一個(gè)空間,故而OGC
與OC
相等??梢蕴骄恳幌吕夏甏卸鄠€(gè)空間的時(shí)候有什么差異。- JVM參數(shù)
-Xmx512m
最大堆內(nèi)存等于NGCMX + OGCMX
- JVM參數(shù)
-Xms512m
最小堆內(nèi)存等于NGCMN + OGCMN
- 將堆的最小值
-Xms
參數(shù)與最大值-Xmx
參數(shù)設(shè)置為一樣即可避免堆自動擴(kuò)展。因?yàn)镴VM初始分配的內(nèi)存由-Xms
指定,默認(rèn)是物理內(nèi)存的1/64
;JVM最大分配的內(nèi)存由-Xmx
指定,默認(rèn)是物理內(nèi)存的1/4
。默認(rèn)空余堆內(nèi)存小于40%時(shí),JVM就會增大堆直到-Xmx
的最大限制;空余堆內(nèi)存大于70%時(shí),JVM會減少堆直到-Xms
的最小限制。因此服務(wù)器一般設(shè)置-Xms
、-Xmx
相等以避免在每次GC后調(diào)整堆的大小。對象的堆內(nèi)存由稱為垃圾回收器的自動內(nèi)存管理系統(tǒng)回收。 - Full GC觸發(fā)條件:
- 調(diào)用
System.gc
時(shí) - 老年代空間不足
- 方法區(qū)空間不足
- 通過Minor GC(新生代GC)后進(jìn)入老年代的平均大小大于老年代的可用內(nèi)存
- 由Eden區(qū)、From Space區(qū)向To Space區(qū)復(fù)制時(shí),對象大小大于To Space可用內(nèi)存,則把該對象轉(zhuǎn)存到老年代,且老年代的可用內(nèi)存小于該對象大小
JVM參數(shù)-XX:MetaspaceSize
元空間初始化內(nèi)存大小,默認(rèn)是20.79MB,超過20.79MB后,每次元空間擴(kuò)增都會觸發(fā)Full GC,所以這個(gè)值設(shè)大一點(diǎn)可以減少Full GC次數(shù)。
JVM參數(shù)-XX:MaxMetaspaceSize
元空間最大內(nèi)存大小,默認(rèn)是無限(超過宿主機(jī)內(nèi)存視為與宿主機(jī)內(nèi)存一致),設(shè)置這個(gè)值,可以避免在發(fā)生故障時(shí)占用大量宿主機(jī)內(nèi)存資源,影響其他服務(wù)。
列代碼 | 列名 | 容量(kB) | 容量(MB) |
---|---|---|---|
NGCMN | 初始新生代空間容量 | 174592.0 | 170.5 |
NGCMX | 最大新生代空間容量 | 174592.0 | 170.5 |
NGC | 當(dāng)前新生代容量 | 174592.0 | 170.5 |
S0C | 當(dāng)前幸存者空間0容量 | 7680.0 | 7.5 |
S1C | 當(dāng)前幸存者空間1容量 | 8704.0 | 8.5 |
EC | 當(dāng)前Eden(伊甸園)區(qū)空間容量 | 157184.0 | 153.5 |
OGCMN | 初始老年代空間容量 | 349696.0 | 341.5 |
OGCMX | 最大老年代空間容量 | 349696.0 | 341.5 |
OGC | 當(dāng)前老年代空間容量 | 349696.0 | 341.5 |
MCMN | 初始元空間容量 | 0.0 | 0 |
MCMX | 最大元空間容量 | 1136640.0 | 1,110 |
MC | 當(dāng)前元空間容量 | 98280.0 | 95.9765625 |
CCSMN | 壓縮的類空間初始容量 | 0.0 | 0 |
CCSMX | 壓縮的類空間最大容量 | 1048576.0 | 1,024 |
CCSC | 當(dāng)前壓縮的類空間容量 | 11904.0 | 11.625 |
YGC | 新生代GC事件數(shù)量 | 46 | |
FGC | 完整GC事件數(shù)量 | 4 |
1.4 也可以通過jstat -gc來統(tǒng)計(jì)
root@7f9fbd4518a4:/# jstat -gc -h 20 1 250 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 10240.0 10240.0 2416.0 0.0 154112.0 123601.6 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123601.6 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123601.6 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071 10240.0 10240.0 2416.0 0.0 154112.0 123893.9 349696.0 60088.4 81112.0 75681.7 9432.0 8462.8 38 1.640 3 0.431 2.071
說明:
列代碼 | 列名 | KB | MB | 備注 |
---|---|---|---|---|
S0C | 幸存者空間0容量 | 10240.0 | 10 | |
S1C | 幸存者空間1容量 | 10240.0 | 10 | |
S0U | 幸存者空間1利用率 | 2416.0 | 2.35 | |
S1U | 幸存者空間1利用率 | 0.0 | 0.0 | |
EC | Eden(伊甸園)空間容量 | 154112.0 | 150.5 | |
EU | Eden(伊甸園)空間利用率 | 123601.0 | 120.70 | |
OC | 老年代空間容量 | 349696.0 | 341.5 | |
OU | 老年代空間利用率 | 60088.0 | 58.67 | |
MC | 元空間容量 | 81112.0 | 79.21 | |
MU | 元空間利用率 | 75681.7 | 73.90 | |
CCSC | 壓縮類空間容量 | 9432.0 | 9.21 | Compressed class space capacity,對應(yīng)參數(shù)-XX:CompressedClassSpaceSize |
CCSU | 壓縮類空間利用率 | 8462.0 | 8.26 | |
YGC | 新生代GC事件次數(shù) | 38 | ||
YGCT | 新生代GC事件時(shí)間 | 1.640 | ||
FGC | Full GC事件次數(shù) | 3 | ||
FGCT | Full GC事件時(shí)間 | 0.431 | ||
GCT | 總GC時(shí)間 | 2.071 |
1.5 通過jstat -gcutil統(tǒng)計(jì)java進(jìn)程的垃圾收集統(tǒng)計(jì)信息
不限制采集次數(shù),采集過程中盡量模擬一般情況下的系統(tǒng)調(diào)用情況,直到觸發(fā)gc事件。
觸發(fā)一次新生代GC事件Minor GC
(觀察YGC
數(shù)量+1)
root@21e4300860c8:/# jstat -gcutil -h 20 1 250 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 8.68 98.93 16.94 92.54 89.70 49 1.761 4 0.908 2.669 0.00 8.68 98.96 16.94 92.54 89.70 49 1.761 4 0.908 2.669 0.00 8.68 98.96 16.94 92.54 89.70 49 1.761 4 0.908 2.669 0.00 8.68 98.96 16.94 92.54 89.70 49 1.761 4 0.908 2.669 0.00 8.68 98.96 16.94 92.54 89.70 49 1.761 4 0.908 2.669 6.80 0.00 0.00 16.95 92.52 89.72 50 1.766 4 0.908 2.673 6.80 0.00 0.74 16.95 92.52 89.72 50 1.766 4 0.908 2.673 6.80 0.00 1.27 16.95 92.52 89.72 50 1.766 4 0.908 2.673 6.80 0.00 2.67 16.95 92.52 89.72 50 1.766 4 0.908 2.673 6.80 0.00 2.67 16.95 92.52 89.72 50 1.766 4 0.908 2.673 6.80 0.00 2.67 16.95 92.52 89.72 50 1.766 4 0.908 2.673 6.80 0.00 2.67 16.95 92.52 89.72 50 1.766 4 0.908 2.673
觸發(fā)一次完整GC事件Full GC
,如果空間過大,一般情況下無法人為觸發(fā),需要通過時(shí)間等待(項(xiàng)目啟動時(shí)間除以FGC
可知多長時(shí)間觸發(fā)一次Full GC),一般是1小時(shí)觸發(fā)一次Full GC。
或許也可以讓survivor
空間利用率接近100%觸發(fā)Full GC。
root@21e4300860c8:/# jstat -gcutil -h 20 1 250 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 99.67 53.34 19.88 93.38 90.50 45 1.680 3 0.627 2.308 0.00 99.67 55.03 19.88 93.38 90.50 45 1.680 3 0.627 2.308 0.00 99.67 55.03 19.88 93.38 90.50 45 1.680 3 0.627 2.308 0.00 99.67 55.03 19.88 93.38 90.50 45 1.680 3 0.627 2.308 0.00 99.67 56.72 19.88 93.38 90.50 45 1.680 3 0.627 2.308 0.00 99.67 56.72 19.88 93.38 90.50 45 1.680 3 0.627 2.308 28.13 0.00 0.00 21.17 93.02 90.13 46 1.729 4 0.627 2.356 0.00 0.00 0.00 16.94 92.41 89.38 46 1.729 4 0.908 2.637 0.00 0.00 0.84 16.94 92.41 89.38 46 1.729 4 0.908 2.637 0.00 0.00 0.84 16.94 92.41 89.38 46 1.729 4 0.908 2.637 0.00 0.00 0.84 16.94 92.41 89.38 46 1.729 4 0.908 2.637 0.00 0.00 0.90 16.94 92.41 89.38 46 1.729 4 0.908 2.637 0.00 0.00 0.92 16.94 92.41 89.38 46 1.729 4 0.908 2.637 0.00 0.00 0.92 16.94 92.41 89.38 46 1.729 4 0.908 2.637
1.6 查看元空間情況
# 查看java實(shí)例的某個(gè)參數(shù) # 查看MetaspaceSize的值,默認(rèn)是-XX:MetaspaceSize=21807104(20.79 MB) jinfo -flag MetaspaceSize <jvmid> # 查看MaxMetaspaceSize的值,默認(rèn)是-XX:MaxMetaspaceSize=18446744073709547520(數(shù)值超過宿主機(jī)最大內(nèi)存,視為無限或與宿主機(jī)一致) jinfo -flag MaxMetaspaceSize <jvmid>
1.7 查看docker容器狀態(tài)
# 在docker容器外部(宿主機(jī))終端 docker stats # 查看某個(gè)docker容器的狀態(tài) docker stats <container_name | id>
命令結(jié)果如下:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 38b70395877a knx-organization-service 0.49% 426.4MiB / 3.682GiB 11.31% 4.88MB / 4.35MB 47.6MB / 0B 57 7f9fbd4518a4 user-account-service 0.38% 479.4MiB / 3.682GiB 12.71% 1.84MB / 2.67MB 72.1MB / 0B 48
說明:
列名 | 描述 |
---|---|
CONTAINER ID and Name | 容器的ID和名稱 |
CPU % and MEM % | 容器正在使用的主機(jī)CPU和內(nèi)存的百分比 |
MEM USAGE / LIMIT | 容器正在使用的總內(nèi)存以及允許使用的總內(nèi)存量 |
NET I/O | 容器通過其網(wǎng)絡(luò)接口發(fā)送和接收的數(shù)據(jù)量 |
BLOCK I/O | 容器已從主機(jī)上的塊設(shè)備讀取和寫入的數(shù)據(jù)量 |
PIDs | 容器創(chuàng)建的進(jìn)程或線程數(shù) |
I/O設(shè)備大致分為兩類:塊設(shè)備和字符設(shè)備。塊設(shè)備將信息存儲在固定大小的塊中,每個(gè)塊都有自己的地址。
數(shù)據(jù)塊的大小通常在512字節(jié)到32768字節(jié)之間。塊設(shè)備的基本特征是每個(gè)塊都能獨(dú)立于其它塊而讀寫。磁盤是最常見的塊設(shè)備
基于結(jié)果第一條可知:
- docker容器的內(nèi)存最大限制是
3.682GiB
,實(shí)際上就是宿主機(jī)的整個(gè)內(nèi)存,相當(dāng)于無限制。 - docker容器已使用的內(nèi)存大小是
426.4MiB
,與11.31% * 3.682GiB
一致,實(shí)際上就是容器內(nèi)java進(jìn)程的實(shí)際內(nèi)存使用大?。ê芙咏?,說明docker容器除了服務(wù)外沒有多少額外內(nèi)存消耗。 - docker容器內(nèi)的進(jìn)程或線程數(shù)為57,進(jìn)程只有一個(gè)java服務(wù),所以可以視為java服務(wù)的線程數(shù)量。
1.8 計(jì)算性能參數(shù)
已知當(dāng)前老年代空間容量為341.5 MB
,再根據(jù)新生代GC和Full GC兩種事件過程采集的結(jié)果可以計(jì)算出:
- 老年代空間利用率:16.94% ~ 21.17%
- 老年代空間利用大小區(qū)間:57.8501 MB ~ 72.29555 MB
- 默認(rèn)老年代占堆內(nèi)存的2/3,可以計(jì)算出適合的最小堆大小:72.29555/0.66=109.53871 MB
- 將最小堆大小往上推一個(gè)最接近的1024整除數(shù):1024/8=128 MB
- 非堆內(nèi)存不會被垃圾收集,可以視為永久代,當(dāng)前使用了多少,基本上就只需要多少,根據(jù)
CCSC
往上推算最接近的1024整除數(shù):1024/64=16 MB - 當(dāng)前線程為57個(gè),考慮到當(dāng)前實(shí)例是開發(fā)環(huán)境,并發(fā)率很低,算作最大線程為100個(gè)
2. 修改JVM參數(shù)-Xmx、-Xms、-XX:MetaspaceSize、-XX:MaxMetaspaceSize
Java8開始已經(jīng)移除了永久代空間(PermGen或permanent generation)即-XX:PermSize
、-XX:MaxPermSize
兩個(gè)參數(shù)是無效的。
取而代之的是元空間(metaspace):
-XX:MetaspaceSize
:最小元空間大?。翰⒎浅跏蓟臻g大小,元空間一開始是0,并且不斷擴(kuò)增,直到MetaspaceSize,都不會觸發(fā)Full GC,而一旦擴(kuò)增超過MetaspaceSize后,每次擴(kuò)增都會觸發(fā)Full GC-XX:MaxMetaspaceSize
:最大元空間大?。簲U(kuò)增的上限,默認(rèn)是無限,設(shè)置一個(gè)值,避免一個(gè)服務(wù)因錯(cuò)誤地不斷加載類而占用整個(gè)服務(wù)器的內(nèi)存,從而影響其他服務(wù)的運(yùn)行。
修改項(xiàng)目鏡像的Dockerfile
中java
命令的JVM參數(shù)
java \ -Xmx128m \ -Xms128m \ -XX:MetaspaceSize=128m \ -XX:MaxMetaspaceSize=256m \ ......
并且重新構(gòu)建鏡像并運(yùn)行。
3. 預(yù)估Docker容器的內(nèi)存限制
Max memory = [-Xmx] + [-XX:MaxMetaspaceSize] + number_of_threads * [-Xss]
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 基于spring-boot和docker-java實(shí)現(xiàn)對docker容器的動態(tài)管理和監(jiān)控功能[附完整源碼下載]
- 使用Kubernetes和Docker部署Java微服務(wù)詳細(xì)代碼
- Docker中Java基礎(chǔ)鏡像OpenJDK和OracleJDK使用方法
- docker-compose java.net.UnknownHostException問題
- Docker啟動容器報(bào)錯(cuò):Ports are not available的解決方案
- Docker使用java項(xiàng)目工程的部署
- Docker部署Java應(yīng)用程序的實(shí)現(xiàn)步驟
- Java(SpringBoot)項(xiàng)目打包(構(gòu)建)成Docker鏡像的幾種常見方式
相關(guān)文章
使用Docker部署Dashdot服務(wù)器儀表盤的步驟
Dashdot是一款簡單、實(shí)用的開源服務(wù)器儀表盤,設(shè)計(jì)時(shí)考慮到了玻璃形態(tài),它旨在用于較小的?VPS?和私人服務(wù)器,這篇文章主要介紹了使用Docker部署Dashdot服務(wù)器儀表盤,需要的朋友可以參考下2022-12-12使用docker部署java項(xiàng)目運(yùn)行環(huán)境的實(shí)現(xiàn)步驟
本文主要介紹了使用docker部署java項(xiàng)目運(yùn)行環(huán)境的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01Docker搭建LibreSpeed的實(shí)現(xiàn)步驟
LibreSpeed 是一個(gè)輕量級的網(wǎng)絡(luò)速度測試工具,本文主要介紹了Docker搭建LibreSpeed的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04Docker?link實(shí)現(xiàn)容器互聯(lián)的方式
通過link方式創(chuàng)建容器,然后我們可以使用被link容器的別名進(jìn)行訪問。本文重點(diǎn)給大家介紹Docker?link實(shí)現(xiàn)容器互聯(lián)的方式,感興趣的朋友一起看看吧2021-12-12