当 Activemq 代理为 运行 时 Web 应用程序挂起

Webapp hangs when Active MQ broker is running

我的 spring 网络应用程序(运行ning 在本地码头上)遇到了一个奇怪的问题,它连接到本地 运行ning ActiveMQ 代理以实现 JMS 功能。 一旦我启动代理,应用程序就会变得非常慢,例如具有活动代理的 ApplicationContext 的启动需要永远(即 > 10 分钟,还没有等待足够长的时间来完成)。如果我在 webapp 之后(即在加载 ApplicationContext 之后)启动代理,它是 运行ning 但速度非常非常慢(通常需要 <1s 的请求需要 >30s)。所有操作都需要更长的时间,即使是不涉及 JMS 的操作也是如此。当我 运行 没有 activemq 代理的应用程序时,一切 运行 都很顺利(当然除了 JMS 相关的东西;-))

这是我到目前为止尝试过的:

  1. 已将 ActiveMQ 版本更新至 5.10.1
  2. 使用独立的 ActiveMQ 而不是 maven-plugin
  3. 将代理 运行ning 从一个单独的 JVM(通过活动的 mq maven 插件,通过 Jetty 配置中的 JNDI 查找连接)移动到同一个 JVM(通过 spring 配置启动,没有 JNDI)
  4. 将活动的 mq 传输从 tcp 更改为 vm
  5. 几个 activemq 设置(alwaysSyncSend、alwaysSessionAsync、producerWindowSize)
  6. 使用 CachingConnectionFactory 和 PooledConnectionFactory

在分析线程转储 (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)

非常感谢任何帮助!

我找到了问题的原因并且能够修复它: 我们将事务管理器传递给 AbstractMessageListenerContainer。在生产中,在本地码头环境中使用 XA-Transactionmanager,仅使用 JPATransactionManager。显然,JMS 一直在等待提交 XA 事务,这在本地环境中从未发生过。 通过覆盖本地环境的 AbstractMessageListenerContainer 的 bean 定义而不设置 transcationmanager 但使用 sessionTransacted="true" 一切正常。 我认为它可能与启用 ActiveMQ 日志记录的事务处理有关。有了这个,我发现交易有问题(transactionContext.getTransactionId() 返回 null)。