5G最大堆内存的JVM进程占满云主机8G内存该何去何从(一)

简介: 一步一步的将理论用于实战,JVM,原来如此深不见底~

背景

运维反馈,经常接到有Java进程内存占用云主机实例93%的告警,当内存持续增高,云主机会对Java进行重启,这也会影响现行业务,对实际服务有所影响。查看服务启动参数后发现最大堆内存为5G,但常常增长到7个多G,到最后出现告警及自动重启的情况,疑惑为什么之前没有类似情况暴露,回忆了下,新业务多数在此应用上开发,有进1个月的时间每天重启,导致问题来不及暴露,不禁为此展开了对该服务与JVM的研究与探讨。

排查

项目背景

项目使用openjdk8,框架为spring boot,由于该Java进程本身启动参数只设置了堆内存大小,及元空间大小,没有指定垃圾回收器也就是hotspot默认的parallel scavenge/parallel old,该GC以吞吐量优先著称,适合不需要太多交互的任务,并不适合该服务,并且gc日志的输出参数在jar 包后,被认为是spring boot项目的参数,未被认为是JVM的参数 ,因此先修复gc日志的输出,以及当oom时输出dump文件,由于直接dump进程的堆内存是对业务有影响的,而且无法自己亲自操作服务器,所以没有选择直接dump JVM的堆。

原来的启动参数如下:

java-XX:MetaspaceSize=512m-XX:MaxMetaspaceSize=512m-Xms5G-Xmx5G-Xmn2G-server-jar/home/active.jar--spring.profiles.active=prod-Xloggc:/home/logs/activegc.log-XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=5-XX:GCLogFileSize=20M-XX:+PrintGCDetails-XX:+PrintGCDateStamps-XX:+PrintGCCause

初次修改

在垃圾收集器的选择上,我们选择一台服务器使用默认的, 一台使用cms垃圾收集器,之后基于gc日志来分析堆内存是否有问题。

#主机一使用-XX:+UseConcMarkSweepGCcms垃圾处理器java-XX:MetaspaceSize=512m-XX:MaxMetaspaceSize=512m-Xms5G-Xmx5G-Xmn2G-XX:+UseConcMarkSweepGC-Xloggc:/home/logs/activegc.log-XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=5-XX:GCLogFileSize=100M-XX:+PrintGCDetails-XX:+PrintGCDateStamps-XX:+PrintGCCause-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/logs/-server-jar/home/active.jar--spring.profiles.active=prod#主机二使用默认垃圾收集器java-XX:MetaspaceSize=512m-XX:MaxMetaspaceSize=512m-Xms5G-Xmx5G-Xmn2G-Xloggc:/home/logs/activegc.log-XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=5-XX:GCLogFileSize=100M-XX:+PrintGCDetails-XX:+PrintGCDateStamps-XX:+PrintGCCause-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/logs/-server-jar/home/active.jar--spring.profiles.active=prod

当默认垃圾收集器对应的Java进程触发告警时,到处gc日志,进行分析

image.png

使用cms垃圾收集器分析gc日志

image.png

以上使用的gc日志分析工具为https://gceasy.io/ 从两个日志分析来看,堆内存是比较健康的,同一时间启动以来,发现默认的垃圾收集器对内存的使用上来说是比较重的,那么我们从而得到一个简单的结论就是可以直接用cms 垃圾收集器来替换,这样可以延缓内存增速飞快导致触发告警并重启。从cms 的日志来看,老年代的内存可以少给一些,因为触发告警了需要手动重启,正好修改一下cms 垃圾收集器的java进程的内存分配,看cms进程内存的利用率并不是很高,所以替换默认垃圾收集器,使用G1看看是否更有效果。

总结

当默认的垃圾收集器触发告警时,cms 垃圾收集器内存对应的云主机内存使用率为60%,前途一片光明,战斗取得了阶段性胜利,但并不能止步,还需要进一步的研究与探索,堆内存如此健康,到底是怎么占满了8G内存的呢?

敬请期待。。。

大家加油!!!

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
11天前
|
存储 Java
深入理解Java虚拟机:JVM内存模型
【4月更文挑战第30天】本文将详细解析Java虚拟机(JVM)的内存模型,包括堆、栈、方法区等部分,并探讨它们在Java程序运行过程中的作用。通过对JVM内存模型的深入理解,可以帮助我们更好地编写高效的Java代码,避免内存溢出等问题。
|
2天前
|
存储 缓存 算法
深入浅出JVM(二)之运行时数据区和内存溢出异常
深入浅出JVM(二)之运行时数据区和内存溢出异常
|
2天前
|
存储 缓存 Java
JVM 运行时内存篇
JVM 运行时内存篇
7 0
|
3天前
|
Arthas 监控 Java
JVM工作原理与实战(三十一):诊断内存泄漏的原因
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了诊断内存溢出的原因、MAT内存泄漏检测的原理等内容。
11 0
|
3天前
|
存储 Arthas 监控
JVM工作原理与实战(三十):堆内存状况的对比分析
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了堆内存状况的对比分析、产生内存溢出的原因等内容。
10 0
|
3天前
|
Arthas Prometheus 监控
JVM工作原理与实战(二十九):监控内存泄漏的工具
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了解决内存溢出的步骤、Top命令、VisualVM、Arthas、Prometheus + Grafana等内容。
10 0
|
3天前
|
监控 Java 测试技术
JVM工作原理与实战(二十八):内存溢出和内存泄漏
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了内存溢出与内存泄漏、内存泄漏的常见场景、解决内存溢出的步骤等内容。
JVM工作原理与实战(二十八):内存溢出和内存泄漏
|
3天前
|
监控 安全 Java
JVM工作原理与实战(二十一):内存管理
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了不同语言的内存管理(C/C++、Java)、垃圾回收的对比(自动垃圾回收与手动垃圾回收)等内容。
11 0
|
3天前
|
Arthas 存储 监控
JVM工作原理与实战(二十):直接内存
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了直接内存、在直接内存上创建数据等内容。
|
3天前
|
存储 监控 Java
JVM工作原理与实战(十七):运行时数据区-栈内存溢出
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了栈内存溢出、设置虚拟机栈的大小等内容。
10 0