在ActiveMQ中是否可以限制开放消费者交易所需的内存?

时间:2014-04-10 01:56:31

标签: java activemq

我目前正在使用ActiveMQ 5.7.0和KahaDB,但如果需要可以升级。我使用嵌入式代理,并且有经验创建插件并以编程方式控制代理配置。

在我的应用程序中,我在交易会话中创建了一个消费者。消费者正在将数据传输到另一个服务(而不是ActiveMQ)。这项服务允许我提交工作,但这些提交可能很昂贵。我发现会话消耗的未提交消息保存在代理的内存中。这要求我提交比我想要的更多的时间来释放代理内存资源。理想情况下,我想控制何时发生提交,而不必考虑ActiveMQ内存利用率。

我目前的算法是:

  • 收到消息
  • 翻译消息并清除正文以保存消费者空间(msg.clearBody()
  • 将msg发送到服务
  • 定期检查队列内存利用率
  • 如果代理内存严重,则提交

我希望能够做到的是:

  • 收到消息
  • 翻译消息并清除正文以保存消费者空间(msg.clearBody()
  • 将msg发送到服务
  • 定期检查队列磁盘利用率
  • 如果代理磁盘利用率严重,则提交

我看过File based cursor,看起来它可以做我需要的东西,但是当我尝试使用它时,它似乎没有达到预期的效果。过去还曾在ActiveMQ用户的讨论组中询问similar question

更新
澄清。我们的问题不在于打开事务中的消息数量,而在于消息的大小。我们的应用程序经常需要处理大邮件(> 50MB)。除了这个问题,ActiveMQ与这种大小的消息一起工作得很好。我们正在寻找的是在内存资源耗尽时在代理上触发类似msg.clearBody()的方法。然后,如果再次需要消息内容,则代理可以从磁盘支持的存储重新加载它们。我们愿意开发插件或扩展来实现这一目标。

1 个答案:

答案 0 :(得分:4)

正如我在ActiveMQ留言板上所述...... http://activemq.2283324.n4.nabble.com/Transactions-and-memory-consumption-td4224862.html

在事务处理过程中,ActiveMQ无法从内存中清除这些消息。事务的数据结构包含消息引用。

一旦在内存中存在队列,就只能通过以下方式之一向JVM GC提供消息:

  • 确认消息
  • 消息到期
  • 完成消费消息的交易
  • 用于清除队列的管理工具

我对用例非常好奇,因为代理具有良好的JVM堆大小,因此代理可以在内存中保存大量消息。通过增加数量可以看到什么样的性能数字以及预期会有多少改进?应该可以通过定期添加Session.commit()调用来测量整体改进,或者对于XA-Transaction,通过使用非事务处理队列消耗来测量总体改进。

如果下游提交时间很长,那么使用并行处理提高吞吐量的策略可能会有效:

  • 填写交易
  • 开始提交
  • 同时,继续将收到的消息用于下一个交易
  • 填写第二笔交易
  • 等待第一笔交易提交完成
  • 如果第一次交易失败,请回滚第二次
  • 如果第一个事务成功,则提交第二个事务并启动相同的
  • 的下一次迭代

当然,从长远来看,如果下游系统无法跟上传入消息的速度,就不可能防止缓慢消耗问题导致代理过载。