猿问

Apache ActiveMQ 中的内存泄漏

我是 Apache ActiveMQ 的新手,在 ActiveMQ 中发送和存储大量大消息(最大的大约 100mb)时遇到了一些麻烦。消息是持久的,所以据我所知它们存储在硬盘驱动器上,而不是内存中。但奇怪的是,当数据库大小(KahaDB 文件夹)达到 2.8Gb(4Gb jvm 堆的 70%)时,ActiveMQ 崩溃了。似乎 ActiveMQ 仍然将所有消息存储在内存中。我需要首先存储所有消息,然后我将全部使用它们。


我的配置 activemq.xml


<policyEntry queue=">" producerFlowControl="false" memoryLimit="100MB">

    <pendingQueuePolicy>

        <fileQueueCursor />

    </pendingQueuePolicy>

</policyEntry>

...

<systemUsage>

    <systemUsage>

        <memoryUsage>

            <memoryUsage percentOfJvmHeap="70" />

        </memoryUsage>

        <storeUsage>

            <storeUsage limit="100 gb"/>

        </storeUsage>

        <tempUsage>

            <tempUsage limit="50 gb"/>

        </tempUsage>

    </systemUsage>

</systemUsage>

...

<transportConnectors>

    <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=204857600"/>

</transportConnectors>

这就是我如何用 java 发送消息。Try-with-resources 关闭所有。


try (Connection conn = queueConnFactory.createConnection();

        Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);

        MessageProducer producer = session.createProducer(getTargetQueue())) {


      ObjectMessage message = session.createObjectMessage(transferMessage);

      producer.send(message);

    }


喵喔喔
浏览 196回答 1
1回答

慕仙森

在这一点上,我没有看到任何内存泄漏的证据。仅仅因为代理内存不足并不意味着存在泄漏。您可能根本没有为您的用例提供足够的 JVM 堆。此外,仅仅因为代理使用某种数据库(即 KahaDB)将消息存储到磁盘并不意味着代理很像数据库。代理仍将尽可能多地在内存中存储消息数据,尽管消息与您的断言相反已持久保存到磁盘。一旦将消息数据写入磁盘就从内存中清除消息数据,然后在消费者需要时立即从磁盘重新加载它,这将是非常低效的。还有一个问题是代理必须在不将它们写入磁盘的情况下跟踪非持久性消息。如果您只是要存储所有数据然后稍后检索它,那么最好只使用数据库,因为数据库更适合这种用例。消息代理通常更适合消费者与生产者同时活动且消息不在代理上建立但在到达后立即发送给消费者的用例。您的代码片段可能是一种反模式。JMS 连接是线程安全的,可以重复使用。为每条发送的消息打开和关闭连接是一种反模式,事实上,如果应用程序除了发送一条单独的消息之外还执行任何其他 JMS 工作。最后,您可以考虑转向ActiveMQ Artemis(即下一代 ActiveMQ),因为它支持“大”消息——这是 ActiveMQ 5.x 所缺乏的。
随时随地看视频慕课网APP

相关分类

Java
我要回答