记一次服务器内存占用过高导致的简单JVM调优

记一次服务器内存占用过高导致的简单JVM调优

继安装GPE分布式监控系统对服务器进行监控之后,陆续发现服务器内存占用率很高。有时间就对服务器上的应用进行逐一排查。
在这里插入图片描述

1.查看服务器状态

使用top命令看了下系统的状态:

top -c

看到系统的整体负载和cpu并不高,但是内存使用比较高(15.6/16),遂使用M进行内存占用排序
在这里插入图片描述

可以看到其中占用内存较大的应用均为java应用,而且应用数量有20+,每个java应用的启动参数设置的都比较大。导致服务器内存占用很高。
如何在保证应用正常使用的同时,减小应用占用内存,修改启动参数,成为了解决问题的关键。

2.优化-Xms,-Xmx参数

我们首先选用内存占用比例最高的PID:32477的java应用来进行分析,我们看到在启动参数中该应用配置的启动参数为

-Xms2048m -Xmx2048m

堆内存分配了2个G,那么怎么确定应用是否用到了这么大的堆内存呢?

第一步

我们jstat命令来查看一下JVM的GC情况,并通过GC信息来确定下一步优化的侧重点:

#即会每5秒一次显示进程号为32477的java进成的GC情况,一共显示5次
jstat -gc 32477 5000 5

结果如下图:
在这里插入图片描述
YGC平均耗时: 0.353s/9=0.8ms

FGC平均耗时:基本为0

平均大约40ms才会产生一次YGC

看起来似乎不错,YGC触发的频率不高,FGC的耗时也不高,但这样的内存设置是不是有些太浪费呢?(后续可以使用jmap工具强制触发FullGC来观察FullGC之后的老年代存活对象大小,使用命名jmap -dump:live,format=b,file=heap.bin <pid>)

第二步

我们再使用jmap工具来查看堆内存使用情况

 jmap -heap 32477

结果如下图:
在这里插入图片描述

可以看到老年代的内存占用仅为50M左右。那么根据老年代内存占用我们应该怎么分配堆内存设置呢,依据的原则是根据Java Performance里面的推荐公式来进行设置。
在这里插入图片描述

具体来讲:

Java整个堆大小设置,Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍

永久代 PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍。

年轻代Xmn的设置为老年代存活对象的1-1.5倍。

老年代的内存大小设置为老年代存活对象的2-3倍。

按照上述规则,按照整个堆大小是老年代(FullGC)之后的3-4倍计算的话,设置各代的内存应该情况如下:

 Xmx=512m Xms=256m Xmn=64m PermSize=64m 

老年代的大小为 (256-64=192m)为老年代存活对象大小的3倍左右

3.优化-XX:MetaspaceSize,-XX:MaxMetaspaceSize参数

MetaspaceSize含义

MetaspaceSize容量触发FGC的阈值。比如-XX:MetaspaceSize=256m,当MetaspaceSize容量超过256M时触发FGC,超过设定阈值后MetaspaceSize每扩容一次触发一次FGC;

第一步

我们jstat命令来查看一下JVM的Meta区使用率,并通过来Meta区使用率确定参数配置是否合理:

jstat -gcutil 32477

结果如下图:
在这里插入图片描述

第二步

然后,再通过jstat -gc 32477 5000 5命令查看,结果如下图所示,计算MU/MC即Meta区的使用率确实达到了23.12%,但是MC,即Metaspace Capacity只有322304k,并不是参数MetaspaceSize指定的512m,结果如下图:
在这里插入图片描述

通过以上结果,我们可以发现MetaspaceSize容量设置的过大,导致Meta区使用率太低,浪费了比较多的堆内存。并取消了-XX:InitialBootClassLoaderMetaspaceSize参数的配置(或随着MetaspaceSize的内存分配减少而减少,普通项目配置为64M即可)。修改后的Meta参数配置为:

-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m

InitialBootClassLoaderMetaspaceSize

64位下默认4M,32位下默认2200K,metasapce前面已经提到主要分了两大块,Klass Metaspace以及NoKlass Metaspace,而NoKlass Metaspace是由一块块内存组合起来的,这个参数决定了NoKlass Metaspace的第一个内存Block的大小,即2*InitialBootClassLoaderMetaspaceSize,同时为bootstrapClassLoader的第一块内存chunk分配了InitialBootClassLoaderMetaspaceSize的大小。

设置建议

MetaspaceSize和MaxMetaspaceSize设置一样大;

MetaspaceSize值建议设置为应用稳定运行后1.2-1.5倍,对于大部分项目256m即可.

4.输出GC日志,并使用GC工具查看应用GC情况

通过GC日志可视化分析工具,我们可以很方便的看到JVM各个分代的内存使用情况、垃圾回收次数、垃圾回收的原因、垃圾回收占用的时间、吞吐量等,这些指标在我们进行JVM调优的时候是很有用的,这里我们选用GCeasy。

GCeasy介绍
官网地址:https://gceasy.io/,GCeasy是一款在线的GC日志分析器,可以通过GC日志分析进行内存泄露检测、GC暂停原因分析、JVM配置建议优化等功能,而且是可以免费使用的(有一些服务是收费的)。

第一步

设置GC日志输出参数,在应用启动时,加入对GC日志打印的语句。

GC参数

JVM的GC日志的主要参数包括如下几个:

-XX:+PrintGC 输出GC日志

-XX:+PrintGCDetails 输出GC的详细日志

-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)

-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2017-09-04T21:53:59.234+0800)

-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息

-Xloggc:…/logs/gc.log 日志文件的输出路径

修改应用启动脚本,加入如下启动配置:

-XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc.log

启动应用,在jar包的同级目录获得gc日志文件gc.log

第二步

将上述获得的日志文件导入第三方GC日志分析器:
在这里插入图片描述

JVM的各个分代区域分配的内存及使用峰值的内存
在这里插入图片描述

关键性能指标:吞吐量及GC暂停平均时间、最大时间、各个时间段的比例。
在这里插入图片描述

内存泄漏及fullGC异常
在这里插入图片描述

GC发生的原因、次数、时间等
在这里插入图片描述

4.修改启动参数后,对结果进行验证

经过上述修改,可以看到GPE上内存占用有比较明显的下降。
在这里插入图片描述

总结:

在内存相对紧张的情况下,可以按照上述的方式来进行内存的调优, 找到一个在GC频率和GC耗时上都可接受的一个内存设置,可以用较小的内存满足当前的服务需要

但当内存相对宽裕的时候,可以相对给服务多增加一点内存,可以减少GC的频率,GC的耗时相应会增加一些。 一般要求低延时的可以考虑多设置一点内存, 对延时要求不高的,可以按照上述方式设置较小内存。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
文件上传服务器JVM主要是针对内存管理和GC进行的化。以下是一些常用的方法和步骤: 1. 设置合适的堆内存大小:通过整-Xmx和-Xms参数来设置堆内存的最大和初始大小。根据服务器的硬件配置和应用程序的需求,适当增加堆内存可以提性能,减少GC的频率。 2. 整新生代和老年代的比例:新生代和老年代的比例决定了对象在不同代之间的分配和回收。可以通过整-XX:NewRatio参数来整新生代和老年代的比例。 3. 选择合适的垃圾收集器:根据应用程序的特点和性能需求,选择合适的垃圾收集器。常见的垃圾收集器有串行收集器(-XX:+UseSerialGC),并行收集器(-XX:+UseParallelGC)和CMS收集器(-XX:+UseConcMarkSweepGC)等。不同的垃圾收集器在吞吐量、延迟和内存占用等方面有所区别。 4. 监控和分析GC日志:通过启用-XX:+PrintGC和-XX:+PrintGCDetails参数,可以在控制台输出GC日志。通过分析GC日志,可以了解GC的频率、持续时间和内存回收情况,从而化GC策略和参数设置。 5. 使用堆内存快照进行分析:当JVM发生内存溢出(OOM)异常时,可以通过设置-XX:HeapDumpOnOutOfMemoryError参数来生成堆内存快照。通过分析堆内存快照,可以了解内存泄漏和过度使用的情况,进一步内存管理和对象生命周期。 请注意,具体的JVM方法和步骤应该根据实际情况进行整和化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值