I got a strange problem with my spring webapp (running on local jetty) which connects to a locally running ActiveMQ broker for JMS functionality. As soon as I start the broker the applications becomes incredibly slow, e.g. the startup of the ApplicationContext with active broker takes forever (i.e. > 10mins, did not yet wait long enough for it to complete). If I start the broker after the webapp (i.e. after the ApplicationContext was loaded) it's running but in a very very slow way (requests which usually take <1s take >30s). All operations take longer even the ones without JMS involved. When I run the application without an activemq broker everything runs smoothly (except the JMS related stuff of course ;-) )
我的spring webapp(在本地jetty上运行)有一个奇怪的问题,它连接到本地运行的ActiveMQ代理以实现JMS功能。一旦我启动代理,应用程序就会变得非常慢,例如,使用active broker启动ApplicationContext需要花费很长时间(即> 10分钟,还没有等待足够长的时间来完成)。如果我在webapp之后启动代理(例如,在加载ApplicationContext之后),它正在运行,但是速度非常慢(请求通常需要小于1,需要>30s)。所有操作都需要更长的时间,即使没有涉及到JMS。当我没有activemq代理运行应用程序时,一切运行都很顺利(当然除了JMS相关的内容除外)。
Here's what I tried so far:
以下是我迄今为止所尝试的:
- Updated the ActiveMQ Version to 5.10.1
- 将ActiveMQ版本更新为5.10.1
- Used standalone ActiveMQ instead of maven-plugin
- 使用独立的ActiveMQ代替maven-plugin
- moved the broker running from a separate JVM (via active mq maven plugin, connection via JNDI lookup in jetty config) into the same JVM (started via spring config, without JNDI)
- 将代理从单独的JVM(通过活动的mq maven插件,通过jetty配置中的JNDI查找连接)迁移到相同的JVM(通过spring配置启动,不使用JNDI)
- changed the active mq transport from tcp to vm
- 将活动的mq传输从tcp更改为vm
- several activemq settings (alwaysSyncSend, alwaysSessionAsync, producerWindowSize)
- 几个activemq设置(alwaysSyncSend, alwaysSessionAsync, producerWindowSize)
- Using CachingConnectionFactory and PooledConnectionFactory
- 使用CachingConnectionFactory和PooledConnectionFactory
When analyzing a thread dump (jstack) I see many activemq threads sleeping on a monitor. Which looks like this:
在分析线程转储(jstack)时,我看到许多activemq线程睡在监视器上。它看起来像这样:
"ActiveMQ VMTransport: vm://localhost#0-3" daemon prio=6 tid=0x000000000b1a3000 nid=0x1840 waiting on condition [0x00000000177df000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000f786d670> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:196)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:955)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:917)
at java.lang.Thread.run(Thread.java:662)
Any help is greatly appreciated !
非常感谢您的帮助!
1 个解决方案
#1
0
I found the cause of the issue and was able to fix it: we were passing a transactionmanager to the AbstractMessageListenerContainer. While in production there is a XA-Transactionmanager in use on the local jetty environment only a JPATransactionManager is used. Apparently the JMS is waiting forever for an XA transaction to be commited, which never happens in the local environment. By overriding the bean definition of the AbstractMessageListenerContainer for the local env without setting a transcationmanager but using sessionTransacted="true"
instead everything works fine. I got the idea that it might be related to transaction handling from enabling the ActiveMQ logging. With this I saw that something was wrong with the transaction (transactionContext.getTransactionId()
returned null
).
我找到了问题的原因并能够修复它:我们将一个transactionmanager传递给AbstractMessageListenerContainer。在生产环境中,在本地jetty环境中使用XA-Transactionmanager时,只使用JPATransactionManager。显然,JMS正在等待一个XA事务被引用,这在本地环境中是不会发生的。通过为本地env重写AbstractMessageListenerContainer的bean定义,无需设置收发管理器,而是使用sessionTransacted=“true”,一切都很好。我的想法是,它可能与启用ActiveMQ日志记录的事务处理有关。我看到事务(transactionContext.getTransactionId()返回null)有问题。
#1
0
I found the cause of the issue and was able to fix it: we were passing a transactionmanager to the AbstractMessageListenerContainer. While in production there is a XA-Transactionmanager in use on the local jetty environment only a JPATransactionManager is used. Apparently the JMS is waiting forever for an XA transaction to be commited, which never happens in the local environment. By overriding the bean definition of the AbstractMessageListenerContainer for the local env without setting a transcationmanager but using sessionTransacted="true"
instead everything works fine. I got the idea that it might be related to transaction handling from enabling the ActiveMQ logging. With this I saw that something was wrong with the transaction (transactionContext.getTransactionId()
returned null
).
我找到了问题的原因并能够修复它:我们将一个transactionmanager传递给AbstractMessageListenerContainer。在生产环境中,在本地jetty环境中使用XA-Transactionmanager时,只使用JPATransactionManager。显然,JMS正在等待一个XA事务被引用,这在本地环境中是不会发生的。通过为本地env重写AbstractMessageListenerContainer的bean定义,无需设置收发管理器,而是使用sessionTransacted=“true”,一切都很好。我的想法是,它可能与启用ActiveMQ日志记录的事务处理有关。我看到事务(transactionContext.getTransactionId()返回null)有问题。