由于频繁的垃圾收集导致服务吞吐量低

问题描述 投票:2回答:1

我在具有16GB RAM的系统上运行服务,具有以下配置:

-Xms6144M"
-Xmx6144M
-XX:+UseG1GC
-XX:NewSize=1500M
-XX:NewSize=1800M
-XX:MaxNewSize=2100M
-XX:NewRatio=2
-XX:SurvivorRatio=12
-XX:MaxGCPauseMillis=100
-XX:MaxGCPauseMillis=1000
-XX:GCTimeRatio=9
-XX:-UseAdaptiveSizePolicy
-XX:+PrintAdaptiveSizePolicy

它有大约20个轮询器,每个轮询器都有大小为30的ThreadPoolExecutor来处理消息。最初大约5-6个小时,它每秒能够处理大约130条消息。此后,它每秒只能处理大约40条消息。

我分析了GC日志,发现Full GC变得非常频繁,超过1000MB的数据从Young发展到Old Generation:

YoungGen

OldGen

PromotionYoung

GCPause

看看堆转储我看到很多等待状态的线程类似于:WAITING at sun.misc.Unsafe.park(Native Method)以下类对象获取大多数保留大小:HeapDump

我认为在服务及其相关库中可能存在小的内存泄漏,这些库随着时间的推移而累积,因此增加堆大小只会推迟这一点。或者可能是因为Full GC变得非常频繁,所有其他线程都经常停止(“停止世界”暂停)。需要帮助来找出此行为的根本原因。

java garbage-collection heap-dump throughput g1gc
1个回答
1
投票

GC模式看起来像内存泄漏。

查看堆转储统计信息,我可以看到等待在线程池中执行的3M任务。

我可以推测,您正在使用具有无限任务队列的线程池。您的入站邮件速率大于系统的处理能力,因此积压正在成长,消耗更多内存,最终导致GC死亡。

根据您的情况,您可以限制线程池的队列大小,也可以尝试优化队列任务的内存占用。

限制队列大小会在先前的处理阶段产生背压。如果它是简单的计时器驱动的轮询器,它是线程池的生产者,则效果将是reducer轮询间隔(因为轮询器将阻止等待队列中的空间)。

任务内存占用的优化只会使您的处理能力平均大于入站任务率,并且问题是由于临时激增造成的。

© www.soinside.com 2019 - 2024. All rights reserved.