一次线上CPU和内存占用过高分析
创作时间:
作者:
@小白创作中心
一次线上CPU和内存占用过高分析
引用
CSDN
1.
https://m.blog.csdn.net/fuleigang/article/details/145853587
本文记录了一次系统运行两周后,监控系统频繁发送CPU占比过高,具体分析和后续跟进。
首先登录机器查看具体信息
top - 14:08:46 up 61 days, 7:28, 4 users, load average: 20.24, 18.05, 16.99
Tasks: 309 total, 2 running, 307 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.2 us, 0.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 16265756 total, 198876 free, 15254512 used, 812368 buff/cache
KiB Swap: 16773116 total, 14563704 free, 2209412 used. 154820 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21632 root 20 0 30.263g 0.014t 4116 S 1544 90.7 37889:12 java
1 root 20 0 191984 2276 1264 S 0.0 0.0 0:46.24 systemd
(1) 关键指标解读
- CPU 使用率:
- 99.2% us:表示用户空间进程(Java)几乎耗尽所有 CPU。
- 内存使用:
- 15.25GB/16.26GB:内存已用,剩余仅 198MB,触发频繁的 Swap 交换(2.2GB/16.77GB 已用)。
- 负载平均值:
- 20.24, 18.05, 16.99(1/5/15 分钟),远超 CPU 核心数,说明系统严重过载。
- 异常进程:
- java 进程占用 1544% CPU(相当于近 16 核满载)和 90.7% 内存(14GB),是核心瓶颈。
继续分析:
# 查看进程启动命令和路径
ps -ef | grep 21632
# 查看 Java 应用名称(若通过 jvm 启动)
sudo -u root jps -lv | grep 21632
# 查看 Java 内存参数配置
ps -ef | grep java | grep -o "\-Xmx[0-9a-zA-Z]*"
[linuxadmin@10-11-24-3 ~]$ ps -ef | grep java | grep -o "\-Xmx[0-9a-zA-Z]*"
-Xmx10g
[linuxadmin@10-11-24-3 ~]$ jps -lv
21572 sun.tools.jps.Jps -Dapplication.home=/data/app/apps/java/jdk1.8.0_111 -Xms8m
# 服务分配了10G内存,实际使用已经14G了,明显超出配置内存,继续分析
jcmd 21632 VM.native_memory summary
[root@10-11-24-3 linuxadmin]# jcmd 21632 VM.native_memory summary
21632: Native memory tracking is not enabled
# 没有启动 Native Memory Tracking
# 增加启动参数:-XX:NativeMemoryTracking=detail
lsof -p 21632 | grep 'mem'
# 运行了较多的三方库和本地依赖,存在依赖重复问题,通过增加内存参数限制
- 限制元空间:添加 -XX:MaxMetaspaceSize=256m,防止类元数据无限增长。
- 调整直接内存:若使用 NIO 直接缓冲区,限制 -XX:MaxDirectMemorySize=1g。
- 启用 Native Memory Tracking:重启时添加 -XX:NativeMemoryTracking=detail,持续监控内存分配。
继续查看进程的使用情况:
服务中存在大量的反射,字符串拼接,并发不设置大小,这个主要还是要通过排查代码来处理,后续分析具体dump结合着来进行整改。
再来看看GC情况:
- S0: Survivor 0的使用百分比
- S1: Survivor 1的使用百分比
- E: Eden区的使用百分比
- O: 老年代的使用百分比
- M: 元空间(Metaspace)的使用百分比
- CCS: 压缩类空间的使用百分比
- YGC: 年轻代GC次数
- YGCT: 年轻代GC总耗时
- FGC: Full GC次数
- FGCT: Full GC总耗时
- GCT: 所有GC的总耗时,各参数如上
指标 | 当前值 | 分析 |
---|---|---|
YGC 次数 | 109,349 次 | 年轻代 GC 极度频繁,平均每秒触发约 1.8 次(假设进程启动 61 天)。 |
YGCT | 15,757 秒 | 年轻代 GC 总耗时约 4.38 小时,平均每次 GC 耗时~0.144 秒。 |
FGC 次数 | 113 次 | Full GC 频率较低,但平均每次耗时~1.62 秒,影响显著。 |
O 区使用率 | 36.33% | 老年代占用稳定,未持续增长,无内存泄漏迹象。 |
M/CCS | 33.44% /83.58% | 元空间(Metaspace)和压缩类空间(CCS)使用正常,无溢出风险。 |
核心问题定位
(1) 年轻代 GC 频繁(YGC 过高)
根因:
Eden 区过小:对象快速填满 Eden 区,触发 YGC。
短生命周期对象过多:大量临时对象(如日志字符串、DTO)未被复用。
Survivor 区无效:S0/S1 存活对象快速晋升老年代(但当前 O 区稳定,说明晋升压力可控)。
影响:
应用吞吐量下降(频繁 GC 占用 CPU)。
局部请求延迟波动(YGC 暂停时间累积)。
(2) Full GC 耗时高(FGCT 单次长)
- 根因:
- 老年代碎片化:CMS/G1 未及时合并碎片,触发 Full GC。
- 堆内存不足:老年代预留空间不足,触发并发模式失败(需结合 GC 日志确认)。
优化建议
(1) 调整年轻代内存分配
- 增大 Eden 区:减少 YGC 频率(根据当前堆配置推测,年轻代可能为默认值)。
示例(调整前需确认当前 JVM 参数):
# 假设当前 -Xmx10g,分配 40% 给年轻代(约 4g)
-Xmn4g -XX:SurvivorRatio=8 # Eden=3.5g, S0/S1=0.5g
- 优化 Survivor 区:
- 增大 Survivor 区(-XX:SurvivorRatio=6)或提高晋升阈值(-XX:MaxTenuringThreshold=10)。
(2) 优化对象分配策略
- 复用对象:引入对象池(如 Apache Commons Pool)管理高频创建对象(如日志包装类)。
- 避免大对象直接进入老年代:
-XX:PretenureSizeThreshold=1M # 对象超过 1MB 才直接进入老年代
热门推荐
亭林园:以顾炎武精神传承江南文化
壹点灵教你摆脱生活无意义感
《错会半生》:当生活无意义感袭来,我们该如何应对?
维克多·弗兰克尔教你战胜生活无意义感
昆山:从农业县到“最强县”,改革创新铸就发展奇迹
简单又美味:四种海带炒菜详细做法
AI优化建筑设计:细节提升效率与创新
深圳展示设计:科技与绿色双轮驱动,引领行业新趋势
2024装修趋势解读:生态设计与实用软装指南
ABO血型不合是主因,专家详解新生儿溶血病
夏侯惇:曹操堂兄弟兼首席战将,曹魏开国元勋
大数据助力提升作业批改效率
石榴叶茶、石榴醋、石榴煎饼……枣庄靠一颗石榴果,“链”出百亿大产业
2024春节山东乡村文化旅游节临沂启动仪式在平邑县正式启幕
在家办公时提高领导能力和社交技能
FDA提醒:智能设备血糖监测存风险,传统方法仍最可靠
中国糖尿病诊疗指南更新:三类老人餐后血糖标准明确
“餐盘法”+6分钟运动:职场人餐后血糖管理新方案
紫菜汤这样做,连吃货都直呼绝了!
日本紫菜选购指南:教你挑选优质紫菜
紫菜汤:健康饮食的新宠儿
职场道歉指南:如何真诚挽回人心?
王晓霆教你:如何用真诚道歉促进个人成长
贝琪博士教你:如何通过道歉修复亲子关系
200传承人、13座古窑:景德镇古窑景区的陶瓷文化新生
一日游景德镇:从陶瓷古窑到地质奇观的完美组合
冰箱温湿度监测:守护食品安全的隐形卫士
青菜头炒肉:营养互补的健康之选,这些搭配禁忌要当心
从颜色到弹性:教你选购优质猪肉和青菜
半小时速成营养美味:青菜炒肉制作详解