Я пытаюсь отследить и определить root причину утечки памяти в нашем очень маленьком и простом приложении Spring Boot.
Используется следующее: - Spring Boot 2.2.4 - azure -servicebus-jms-spring-boot-starter 2.2.1 - MS SQL
Функция: Приложение только отправляет Azure очередь ServiceBus, сохраняет данные и отправляет данные в другой пункт назначения. Это небольшое приложение, поэтому оно легко запускается с 64 мегабайтами памяти, несмотря на то, что я даю ему до 256 мегабайт через опцию Xmx. Важное замечание: очередь отправляется в транзакционном режиме Spring по умолчанию с выделенным JmsTransactionManager, который на самом деле является внутренней TM ChainedTransactionManager вместе с dbTM и дополнительным исходящим JMS TM. Оба объекта JMS ConnectionFactory создаются как CachingConnectionFactory.
Поведение:
После запуска приложения кажется, что все в порядке. Там нет traffi c, поэтому я вижу в журнале, что он открывает транзакции и закрывает при проверке очереди (jms: message-driven-channel-adapter).
Однако через некоторое время, когда по-прежнему нет трафика c, ни одно сообщение не было использовано, память начинает подниматься, как это отслеживается с помощью 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 кучи, и с этого момента он завершается ошибкой OutOfMemory в потоке, открывающем соединения JMS.
--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)
HeapDumps:
Я сделал пару снимков кучи в течение всего этого процесса и посмотрел на то, что увеличивается. Я вижу подозрительное количество объектов ConcurrentHashMap / String / Byte [].
Есть кто-нибудь подсказка / подсказка, что может быть не так в этой настройке, и библиотеки: Spring Boot, Apache qPid, используемый под капотом Azure JMS зависимость et c.? Большое спасибо.
Обновление # 1 У меня есть четкое свидетельство того, что проблема связана с Spring или azure service bus начальная библиотека - не используется клиент qPid. Я бы сказал, что библиотека содержит ошибку, а не Spring, просто мое предположение. Вот как выглядит сбойная установка:
- Существует два назначения JMS и одна БД, каждая с менеджером транзакций
- Существует ChainedTransactionManager, обертывающийся над тремя TM.
- Приложение интеграции Spring, которое подключается к Azure очереди ServiceBus через jms: message-driven-channel-adapter и устанавливает менеджер транзакций на этом компоненте (как создано в пункте 2)
- Запустите приложение. Трафик c в очереди не требуется, через 10 минут приложение обработает sh из-за OutOfMemoryError ... в пределах этих 10 минут я смотрю журнал на уровне отладки, и единственное, что происходит, - это открытие и закрытие транзакций с использованием ChainedTransactionManager ... также, как написано в комментариях, другое важное условие - это третий JMS TransactionManager ... с 2 ТМ он работает и стабилен, с 3 это будет sh ...