将 ActiveMQ 与大量持久性队列 (250) á 1000 个持久性 TextMessages á 10 KB 一起使用时会出现问题。
一个场景需要这些消息在存储中保留很长时间(几天),直到它们被消耗掉(大量数据被分阶段分发给许多消费者,可能会离线几天)。
在 Persistence Store 充满这些消息之后,并且在代理重新启动后,我们可以浏览/使用一些队列 ,直到30 秒后调用 #checkpoint。
此调用导致代理使用所有可用内存,并且永远不会将其释放用于其他任务,例如队列浏览/消费。在内部,MessageCursor 似乎决定没有足够的内存并停止将队列内容传递给浏览器/消费者。
=> 有没有办法通过配置来避免这种行为,或者这是一个错误?
期望是,我们可以在任何情况下使用/浏览任何队列。
下面的设置已经投入生产一段时间了,ActiveMQ 文档中应用了一些建议(目标策略、systemUsage、持久性存储选项等)
- 使用 ActiveMQ 测试行为:5.11.2、5.13.0 和 5.5.1。
- 内存设置:Xmx=1024m
- 爪哇:1.8 或 1.7
- 操作系统:Windows、MacOS、Linux
- PersistenceAdapter:KahaDB 或 LevelDB
- 光盘:足够的可用空间(200 GB)和物理内存(最大 16 GB)。
除了上述设置之外,我们还为代理使用以下设置(顺便说一句:将 memoryLimit 更改为较低的值,如 1mb 不会改变这种情况):
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue=">" producerFlowControl="false" optimizedDispatch="true" memoryLimit="128mb" timeBeforeDispatchStarts="1000">
<dispatchPolicy>
<strictOrderDispatchPolicy />
</dispatchPolicy>
<pendingQueuePolicy>
<storeCursor />
</pendingQueuePolicy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<systemUsage>
<systemUsage sendFailIfNoSpace="true">
<memoryUsage>
<memoryUsage limit="500 mb" />
</memoryUsage>
<storeUsage>
<storeUsage limit="80000 mb" />
</storeUsage>
<tempUsage>
<tempUsage limit="1000 mb" />
</tempUsage>
</systemUsage>
</systemUsage>
如果我们将 destinationPolicy 中的cursorMemoryHighWaterMark设置为更高的值,例如150或600,具体取决于 memoryUsage 和可用堆空间之间的差异,可以稍微缓解这种情况,但在我看来,这对于生产系统来说并不是一个真正的选择看法。
带有来自 Oracle Mission Control 的信息的屏幕截图,显示了从未从内存中释放的那些 ActiveMQTextMessage 实例: