JMeter Java进程中的内存泄漏,它消耗>90%的CPU和80%的内存,同时运行400 TPS的测试48小时

mepcadol  于 2023-10-14  发布在  Java
关注(0)|答案(2)|浏览(180)

我正在运行一个JMeter脚本,400 TPS和48小时,它是REST API脚本。

JMeter版本:5.6.2
JMeter脚本配置如下:

Threads : 500
Ramp Up : 100
Duration: 48 hours
TPS     : 400 Using Throughput Shaping Timer

在测试过程中,我逐渐观察到运行JMeter的负载生成器VM上的CPU和内存利用率不断增加。36-40小时后无React

CPU Utilisation >90% and Memory Utilisation >80%

其中运行JMeter脚本的负载生成器具有8个CPU和16 GB RAM,我已经使用-Xmx 1g和-Xmx 10 g堆配置了JMeter。
我已经采取了线程和堆转储与以下分析:
使用TOP命令确认高CPU和内存利用率的过程详细信息

top - 11:38:00 up 54 days, 12:01,  1 user,  load average: 8.83, 7.98, 8.01
Threads: 541 total,   8 running, 533 sleeping,   0 stopped,   0 zombie
%Cpu(s): 97.9 us,  1.4 sy,  0.0 ni,  0.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16247380 total,  2010332 free, 13876416 used,   360632 buff/cache
KiB Swap:  4190204 total,  3953660 free,   236544 used.  2001252 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
107296 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:12.27 GC Thread#1
107297 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:08.55 GC Thread#2
107298 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:09.84 GC Thread#3
107299 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:08.98 GC Thread#4
107300 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:12.21 GC Thread#5
107301 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:11.67 GC Thread#6
107302 sam_user  20   0   17.1g  12.3g  20572 R 99.9 79.2 293:10.00 GC Thread#7
107273 sam_user  20   0   17.1g  12.3g  20572 R 94.1 79.2 293:08.49 GC Thread#0

获取堆转储后的堆分析:

问题嫌疑人1:

One instance of org.apache.logging.slf4j.Log4jLoggerFactory loaded by 

org.apache.jmeter.DynamicClassLoader @ 0x580103ba0 occupies 83,61,68,864 (17.61%) bytes. 

The memory is accumulated in one instance of 

java.util.concurrent.ConcurrentHashMap$Node[], loaded by <system class loader>, which 

occupies 83,61,68,384 (17.61%) bytes.

Keywords

org.apache.logging.slf4j.Log4jLoggerFactory
org.apache.jmeter.DynamicClassLoader @ 0x580103ba0
java.util.concurrent.ConcurrentHashMap$Node[]

问题嫌疑人2:

1,20,38,109 instances of java.lang.String, loaded by <system class loader> occupy 

1,82,80,04,808 (38.50%) bytes.

These instances are referenced from one instance of 

java.util.concurrent.ConcurrentHashMap$Node[], loaded by <system class loader>, which 

occupies 83,61,68,384 (17.61%) bytes.

Keywords

java.lang.String
java.util.concurrent.ConcurrentHashMap$Node[]

问题嫌疑人3:

1,20,16,586 instances of org.apache.logging.log4j.core.Logger, loaded by 

org.apache.jmeter.DynamicClassLoader @ 0x580103ba0 occupy 1,53,81,23,008 (32.39%) bytes.

These instances are referenced from one instance of 

java.util.concurrent.ConcurrentHashMap$Node[], loaded by <system class loader>, which 

occupies 45,16,41,568 (9.51%) bytes.

Keywords

org.apache.logging.log4j.core.Logger
org.apache.jmeter.DynamicClassLoader @ 0x580103ba0
java.util.concurrent.ConcurrentHashMap$Node[]

我假设这是Apache JMeter的问题,你能提供一个解决方案吗?

5f0d552i

5f0d552i1#

您的“分析”只显示堆使用率太高,garbage collection占用了大量资源。
如果您只有一个HTTP请求采样器,并且观察到内存利用率随着时间的推移而变高,这确实是JMeter中的一个问题,您应该report it via JMeter Github
然而,也可能是你的脚本导致了这种行为,即。你正在创建新的JMeter Variables,并且永远不会删除它们。或者你使用相同的虚拟用户48小时,我不认为这是一个有效的用例。或者你正在使用配置不好的Groovy scripts,它在每次调用时都会生成新的类。或者你正在使用Listeners,它不添加任何值,只积累数据。
因此,如果您遵循JMeter Best Practices并且没有任何外部组件/代码的情况下可以重现问题-这是JMeter问题。否则就是你的测试设计问题了。

0md85ypi

0md85ypi2#

您的JMeter示例中似乎确实存在内存泄漏。然而,没有足够的证据来证明这是由JMeter bug引起的“假设”或结论。
我能看到的唯一线索是,泄漏的对象似乎是大量的Logger示例和ConcurrentHashMap中(几乎)匹配数量的字符串。根据Logger类名,看起来您使用的是log4j 2,而log4j 2使用ConcurrentHashMap来实现日志记录器注册表。因此,一个可能的解释是 something 正在创建过多的不同Logger示例;即具有不同的名称。
我对JMeter问题跟踪器进行了快速搜索,以查找提到“内存泄漏”的问题。没有一个与您的症状明显匹配,但我可能错过了一些东西,而且您给我们的关于JMeter脚本的信息很少。(您可以自行查看这些问题here。)
你能提供一个解决方案吗?
根据您提供的信息,我们无法这样做。
如果我有这个问题,我会使用堆转储分析器来查看ConcurrentHashMap中的条目。假设它是logger注册表Map,那么在键中应该有一个很大的线索。

相关问题