我有一个服务在16 on的系统上运行,配置如下:
-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日志,发现完整的GC变得非常频繁,超过1000MB的数据从年轻一代提升到了老一代:




查看堆转储,我看到许多线程处于等待状态,如下所示:WAITING at sun.misc.Unsafe.park(Native Method)和以下类对象获得最大保留大小:

我认为在服务及其关联库中可能存在小的内存泄漏,随着时间的推移不断积累,因此增加堆大小只会推迟这一过程。或者可能是因为完整的GC变得非常频繁,所有其他线程都非常频繁地被停止("stop the world“暂停)。需要帮助找出这种行为的根本原因。
发布于 2019-05-01 20:58:17
GC模式看起来像是内存泄漏。
查看您的堆转储统计数据,我可以看到线程池中有3M个等待执行的任务。
我可以推测,您正在使用具有无界任务队列的线程池。您的消息入站速率大于系统的处理能力,因此backlog会消耗更多的内存,最终导致GC死亡。
根据您的情况,您可以限制线程池的队列大小,也可以尝试优化队列任务的内存占用。
限制队列大小将在前一处理阶段产生背压。如果是简单的定时器驱动的轮询器,它是线程池的生产者,那么效果将是减少轮询间隔(因为轮询器将阻止等待队列中的空间)。
只有当你的平均处理能力大于入站任务速率时,任务内存占用的优化才会起作用,而问题是由临时激增引起的。
https://stackoverflow.com/questions/55929669
复制相似问题