当前位置: 首页 > 知识库问答 >
问题:

在Spring Azure qPID JMS代码中跟踪内存泄漏

崔绍辉
2023-03-14

我试图在我们非常小且简单的Spring Boot应用程序中跟踪并确定内存泄漏的根本原因。

它使用以下内容:-Spring Boot 2.2.4-azure servicebus jms Spring Boot starter 2.2.1-MSSQL

功能:该应用程序只发送Azure ServiceBus队列,存储数据并将数据发送到其他目的地。这是一个小应用程序,所以它很容易启动64兆的内存,尽管我通过Xmx选项给它最多256兆的内存。重要注意事项是,使用Spring默认事务处理模式和专用JmsTransactionManager调度队列,JmsTransactionManager实际上是ChainedTransactionManager的内部TM,以及dbTM和其他出站JMS TM。这两个JMS ConnectionFactory对象都创建为CachingConnectionFactory。

行为:

一旦应用程序启动,它似乎就可以了。没有流量,所以我可以在日志中看到,在检查队列(jms:消息驱动通道适配器)时,它正在打开事务并关闭。

然而,在一段时间后,当仍然没有流量时,没有一条消息被消耗,内存开始上升,通过JVVM进行监控。

引发了一个错误:

--2020-04-24 11:17:01.443 - WARN 39892 ---   [er.container-10] o.s.j.l.DefaultMessageListenerContainer  : Setup of JMS message listener invoker failed for destination 'MY QUEUE NAME HERE' - trying to recover. Cause: Heuristic completion: outcome state is rolled back; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JMS transaction; nested exception is javax.jms.IllegalStateException: The Session was closed due to an unrecoverable error.

...几分钟后,它到达堆的MAX,从那时起,它在打开JMS连接的线程中因OutOfMemory错误而失败。

--2020-04-24 11:20:04.564 - WARN 39892 ---   [windows.net:-1]] i.n.u.concurrent.AbstractEventExecutor   : A task raised an exception. Task: org.apache.qpid.jms.provider.amqp.AmqpProvider$$Lambda$871/0x000000080199f840@1ed8f2b9
-
java.lang.OutOfMemoryError: Java heap space
        at java.base/java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:61)
        at java.base/java.nio.ByteBuffer.allocate(ByteBuffer.java:348)
        at org.apache.qpid.proton.engine.impl.ByteBufferUtils.newWriteableBuffer(ByteBufferUtils.java:99)
        at org.apache.qpid.proton.engine.impl.TransportOutputAdaptor.init_buffers(TransportOutputAdaptor.java:108)
        at org.apache.qpid.proton.engine.impl.TransportOutputAdaptor.pending(TransportOutputAdaptor.java:56)
        at org.apache.qpid.proton.engine.impl.SaslImpl$SwitchingSaslTransportWrapper.pending(SaslImpl.java:842)
        at org.apache.qpid.proton.engine.impl.HandshakeSniffingTransportWrapper.pending(HandshakeSniffingTransportWrapper.java:138)
        at org.apache.qpid.proton.engine.impl.TransportImpl.pending(TransportImpl.java:1577)
        at org.apache.qpid.proton.engine.impl.TransportImpl.getOutputBuffer(TransportImpl.java:1526)
        at org.apache.qpid.jms.provider.amqp.AmqpProvider.pumpToProtonTransport(AmqpProvider.java:994)
        at org.apache.qpid.jms.provider.amqp.AmqpProvider.pumpToProtonTransport(AmqpProvider.java:985)
        at org.apache.qpid.jms.provider.amqp.AmqpProvider.lambda$close$3(AmqpProvider.java:351)
        at org.apache.qpid.jms.provider.amqp.AmqpProvider$$Lambda$871/0x000000080199f840.run(Unknown Source)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:510)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:518)
        at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1050)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at java.base/java.lang.Thread.run(Thread.java:835)

堆堆:

在整个过程中,我拍摄了几个堆快照,并查看了增加的内容。我可以看到可疑数量的ConTrentHashMap/String/Byte[]对象。

有人知道/提示此设置和库中可能出现的错误吗:Spring Boot、Azure JMS依赖项下使用的Apache qPid等?非常感谢。

更新#1我有明确的证据表明,问题出现在Spring或azure service bus starter库中,而不是自动使用qPid客户端。我猜,图书馆有bug,而不是Spring。这是失败的设置的样子:

  1. 有两个JMS目的地和一个DB,每个都有它的事务管理器
  2. 三个TM上面有ChainedTransactionManager包装。
  3. Spring集成应用程序,通过jms连接到Azure ServiceBus队列:消息驱动通道适配器并在此组件上设置事务管理器(如第2点所创建)
  4. 启动应用程序。,不需要队列上的流量,10分钟后应用程序将因OutOfMemoryError而崩溃...在这10分钟内,我观看了调试级别的日志,唯一发生的事情是使用ChainedTransactionManager打开和关闭事务...另一个重要条件是第三个JMS TransactionManager...有2个TM它工作并且稳定,有3个它会崩溃...

共有1个答案

蒋飞捷
2023-03-14

额外的研究和采取的步骤确定了最可能的根本原因Spring CachingConnectionFactory类。一旦我删除它并仅使用本机类型,问题就消失了,内存消耗配置文件非常不同且健康。

我不得不说,我使用标准构造函数创建了CachingConnectionFactory,但没有进一步配置行为。然而,根据我的经验,这些Spring默认值显然会导致内存泄漏。

过去,我在ActiveMq上有内存泄漏,这必须通过使用CachingConnectionFactory来解决,现在我在使用CachingConnectionFactory时在Azure ServiceBus上有内存泄漏。。奇怪:)在这两种情况下,我都认为这是错误,因为无论是否涉及缓存,内存管理都应该是正确的。

把这当作我的答案。

测试案例:使用自己的TM和两个JMS连接工厂都是CachedConnectionFactory类型接收和发送消息时出现问题。最后我测试了应用程序。CachedConnectionFactory类型的入站连接工厂和出站只是本机类型...也没有内存泄漏。

 类似资料:
  • 问题内容: 我们有一个App Engine应用程序,可将许多较大文件写入Google Cloud Store。这些文件是动态创建的CSV文件,因此我们将Python用作缓冲区和写入该缓冲区的接口。 通常,我们的过程如下所示: 据我们了解,它们本身不需要关闭。而是,仅上述内容和需要被关闭。 我们在由App Engine的任务队列调用的中运行上述过程。最终,在几次调用我们的任务后,我们得到以下错误:

  • 我们有一个应用程序引擎应用程序,它将许多相对较大的文件写入谷歌云商店。这些文件是动态创建的CSV,因此我们使用Python的作为写入该缓冲区的接口。 通常,我们的流程如下所示: 据我们所知,不需要自己关闭。相反,只需要关闭上面的和。 我们在appengine的任务队列调用的

  • 我有内存泄漏,我知道它在哪里(我想是这样的),但我不知道为什么会发生。负载测试以下endpoint(使用服务器)时发生内存泄漏: 我非常肯定对象没有被(垃圾回收器)释放。在每一个请求中,应用程序使用的内存都在增长。我做了一些附加测试: 因此,在每个请求中,我都将big object分配给对象作为其属性。我观察到,有了这个附加属性,内存增长得快得多。在60秒内每完成1000个请求,内存会增加100M

  • 问题内容: 这是我几个月来一直试图寻找的问题。我有一个运行的Java应用程序,它处理xml提要并将结果存储在数据库中。存在间歇性的资源问题,很难追踪。 背景: 在生产包装盒上(问题最明显的地方),我对包装盒的访问不是特别好,并且无法使Jprofiler运行。那个盒子是一个运行centos5.2,tomcat6和java 1.6.0.11的64位四核8GB计算机。它以这些java-opts开头 技术

  • 我们的应用程序中有一个JavaMicorservice,它连接到Postgres以及Phoenix。我们正在使用Spring Boot 2. x。 问题是,我们正在为应用程序执行大约8小时的耐久性测试,我们可以观察到使用的堆在不断增加,尽管我们对VM参数使用了建议,看起来像是内存泄漏。我们分析了堆转储,但根本原因对我们来说并不明确,一些专家能否根据结果提供帮助? 我们实际使用的VM参数是: -XX

  • 问题内容: 我看到了这个Python问题:推迟了AppEngine:跟踪内存泄漏 …同样,我遇到了这个可怕的错误: 总共为384个请求提供服务后,超出了128 MB的软私有内存限制 … 处理此请求后,发现处理此请求的进程使用了​​过多的内存并被终止。这很可能导致新流程用于您的应用程序的下一个请求。如果您经常看到此消息,则可能是应用程序内存泄漏。 根据另一个问题,可能是“实例类”太小而无法运行此应用