旧垃圾收集被填满并且不会清理,可能是因为索引

时间:2018-03-09 11:07:31

标签: java garbage-collection jms hibernate-search infinispan

最近,我尝试使用Hibernate Search索引,并且我正在努力为生产环境找到稳定的解决方案。案例是在野生动物10 AS中我使用HibernateOGM PersistenceContext进行索引。这会自动将数据添加到索引(Infinispan file-cache-store)。

问题是我有一个MDB消耗来自JMS队列的数据,我需要调用这个函数(onMessage,一个队列条目包含大约100万个实体 - 大请求)来保存大约100万个实体并发布它们通过无状态EJB到另一个AMQP队列。

在坚持和发布的同时,我注意到在一段特定的时间后,主要的gc不会发生,并且在旧的gen充满之后,eden空间也变得很强,并且持久化和发布消息的速度有很大的下降。

我的想法是onMessage函数需要一个事务,直到它完成它将所有数据保存在内存或其他东西(索引或持久数据)并且不能清理旧的gen以便能够回滚

我提供一些监控图片。你可以很容易地看到,在两个内存空间(旧的gen和eden)都已满并且试图变空之后,将消息发布到另一个队列的速度会有很大的降低(就像我创建一个作为来自jms的请求的列表中的一个实体,我坚持它们并将它们以for循环发布到rabbitmq队列中。如果是这样的话,有没有办法让索引永远保留在磁盘上?已经尝试过驱逐的最小价值,小块大小等。不能很好地运作。还试图改变GC算法,但我总是在同一个位置。也许另一个infinispan持久性文件存储实现?我现在使用单文件缓存存储,之前使用过软索引缓存存储。有什么建议吗?

由于

Hibernate Search 5.6.1,Infinispan 8.2.4,Hibernate OGM 5.1,Wildfly 10

VisualGC from visualVM

VisualVM

RabbitMQ

JMS Threads

Hibernate Search Sync Thread

1 个答案:

答案 0 :(得分:1)

Infinispan(9.2)的最新版本能够“堆放”存储数据,因此简短的回答是肯定的。但是在选择这样做之前要考虑大局,而不是所有来自堆存储的好处,因为这取决于许多因素。

根据定义,Infinispan意味着缓存内存中的最热数据,默认情况下“在堆上”,因为当它只是Java对象时,这将有助于您的整体性能,因为您可以跳过(反)序列化开销;您需要调整堆大小以适应您正在计划的负载,它不能自动执行此操作。最简单的策略是在启用非常大的堆大小时使用类似工具在负载下观察它,然后将其修剪到合理的大小,你知道它对你的负载有用。

因此,在怀疑泄漏或无限增长之前,首先尝试验证是否只有一个太小的堆用于其峰值操作要求。如果确实存在实际泄漏,您可能首先要尝试升级,因为这些版本已经很老了 - 已经修复了很多问题。