【发布时间】:2020-02-29 16:46:26
【问题描述】:
我有一个 java spring boot 应用程序,它假设运行时间很长,并且整个响应时间也小于 50 毫秒。通常我们能够提供这个服务,但是当老一代接近被填满时,CMS 启动并且我们的响应时间 SLA 违反。有什么策略我可以用来确保完全 GC 永远不会启动。
我的服务器是 IO 密集型的,我们不在内存中存储任何内容,但有大量并发 IO(30k rpm),每个 IO 响应携带大约 3-4MB 的数据。从日志中我观察到,Minor GC 在一秒钟内运行了近 3-4 次,由于 eden 和 Survivor 空间较小(Eden 空间为 600MB,survivor 空间为 75MB),Minor GC 被非常频繁地触发。由于非常频繁的 GC,对象可能会在阈值次要 GCs(15) 中幸存下来,并被提升为老一代。所以我通过制作-XX:NewRatio=1 增加了我的年轻一代空间。
问题仍然存在,我可以在一秒钟内看到分配失败日志(如下所示)3-4 次
[GC (Allocation Failure) 56455.997: [ParNew: 10705358K->222390K(11796480K), 0.0467254 secs] 13148872K->2667031K(24903680K), 0.0468292 secs] [Times: user=0.34 sys=0.00, real=0.05 secs]
使用new relic我监控内存,young gen保持不变,old gen不断增加,下面是snapshot。
我认为对于我的应用程序来说,一个好的堆分配策略是年轻代被不断填充和清空,而老代几乎没有使用,因为我们几乎没有任何长寿命的对象。请建议如何实现上述目标,或者您可能想到的任何更好的策略
【问题讨论】:
-
你找到解决方案了吗?
标签: java memory garbage-collection heap-memory