一次性能调优记录:压测报错out of memory内存溢出【杭州多测师_王sir】【杭州多测师】

一次性能调优记录:压测报错out of memory内存溢出
1、首先这是一段压测的报错日志截图

2、服务器的配置还不错,执行机全64核以上,运存256g以上,服务器80核,512g,所有机器线程数设置655360

3、刚开始以为是jmeter和Tomcat服务器的JVM里面的堆内存,新生代和老年代的参数设置太小了

4、然后进行的设置,设置之后发现还是有问题,发现启动jmeter的时候,配置还是显示默认值,在网上查了说改了配置,也不会显示,暂且就先相信一下

5、分析Out of Memory引起的原因:一般老年代空间不足时,JVM 会对老年代和年轻代进行完全的fullGC。如果 fullGC 后还是无法存放从 Survivor 复制过来的对象,就会出现 OOM(Out of Memory) ,但是这个堆空间设置的这么大,一天估计都不可能有一次老年代的垃圾回收

6、然后为了验证heap的设置是没有问题的打算用jmap -heap 进程号命令去看,但最后发现公司内网没办法用这个命令,所以暂时想不到更好的办法了

7、听网上说xms和xmx参数的单位要用kb或者MB,后来把-xms和-xmx改为10240MB,发现还是没用,继续怀疑是配置没生效

8、同时也用了dstat -tcmnd --disk-util命令去监控CPU和内存等等

9、用了jstat -gcutil 进程号 1 10 命令去看看GC的频率什么的

10、Tomcat的jvm参数在Catalina.sh里面进行设置
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:NewRatio=2 -XX:SurvivorRatio=8"
设置堆内存:-Xms1024m -Xmx1024m
设置新生代内存:-XX:NewSize=256m -XX:MaxNewSize=256m
设置新生代和老年代的比例:-XX:NewRatio=2
设置伊甸园和 Survivor 的比例:-XX:SurvivorRatio=8
设置栈内存:-Xss1m
11、最后通过一系列操作完发现压测10几分钟后,还是会报内存溢出
12、后面发现是因为忘了关察看结果树监听器,以前出现过业务返回数据过大导致内存溢出,这次避开了返回数据大小,忽略了返回数据个数,一般设计的sql语句查询行数超过1w,也会出现内存溢出,返回的个数太多也会出现内存溢出。我是设置的25万,忘了关查看结果树,所以导致报内存溢出的错误,后面关了就没有问题了。

 

关于oom内存溢出的其他知识补充
1)问题原因:
用JMeter压测,有时候当模拟并发请求较大或者脚本运行时间较长时,JMeter会停止,报OOM(内存溢出)错误,原因是JMeter是一个纯Java开发的工具,内存由java虚拟机JVM管理,当内存回收不及时,堆内存不足时,就会报内存溢错误。

内存泄露:应用使用资源之后没有及时释放,导致应用内存中持有了不需要的资源。
内存溢出:应用的内存已经不能满足正常使用了,堆栈已经达到系统设置的最大值,进而导致崩溃。
通常都是由于内存泄露导致堆栈内存不断增大,从而引发内存溢出。
对JMeter而言也是如此,JMeter测试过程中,如果内存溢出的话,一般会出现上图中的提示:java.lang.OutOfMemoryError: Java heap space:意思就是堆内存溢出,不够用了

2)解决方法
知道了报错出现的原因是因为堆内存大小不足引起的,自然而然就会想到内存溢出的解决方法:调整堆内存大小。
步骤(以Windows系统为例,Linux系统类似):
1、打开jmeter.bat文件,按关键字“HEAP”搜索,把原来的配置改为如下:
修改前:

if not defined HEAP (
    rem See the unix startup file for the rationale of the following parameters,
    rem including some tuning recommendations
    set HEAP=-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m
)

修改后:

if not defined HEAP (
    rem See the unix startup file for the rationale of the following parameters,
    rem including some tuning recommendations
    set HEAP=-Xms512m -Xmx4000m
    set NEW=-XX:NewSize=256m -XX:MaxNewSize=512m
)

set HEAP=-Xms512m -Xmx4000m:调整堆内存的大小
set NEW=-XX:NewSize=256m -XX:MaxNewSize=512m:调整堆内存中新生带的大小

注意:
这个值不是越大越好,要根据压测使用的机器而定,一般而言,堆内存的最大值不要超过物理内存的一半,否则容易导致jmeter运行变慢、卡顿甚至内存溢出(因为java本身的垃圾回收机制是动态分配内存,调整的时候其本身会占用很多内存),NEW分配的内存,不宜太大。
2、修改完成后保存,重启JMeter,即可生效。

3)小结
1、这种修改堆大小的方法只适用一部分情况,并不是万能的,当需要模拟的线程数较大时,就需要根据具体情况采用分布式压测的方式了。
2、命令行运行JMeter时,一定要禁用:查看结果树、聚合报告等监听器,因为真的真的真的很消耗内存。

 

posted @ 2022-12-17 15:44  多测师_树哥  阅读(181)  评论(0编辑  收藏  举报