Rabbitmq Spring Amqp消费者在运行一段时间后暂停

Rabbitmq Spring Amqp消费者在运行一段时间后暂停,rabbitmq,spring-amqp,consumer,spring-rabbit,Rabbitmq,Spring Amqp,Consumer,Spring Rabbit,我们有一个具有Ha all策略的2节点RabbitMQ集群。我们在应用程序中使用Spring AMQP与RabbitMQ对话。生产者部分工作正常,但消费者工作了一段时间并暂停。生产者和消费者作为不同的应用程序运行。更多关于消费者部分的信息 我们将SimpleMessageListenerContainer与ChannelAwareMessageListener一起使用,使用手动ack模式和默认预取(1) 在我们的应用程序中,我们创建队列(按需)并将其添加到侦听器中 当我们从10个Concurr

我们有一个具有Ha all策略的2节点RabbitMQ集群。我们在应用程序中使用Spring AMQP与RabbitMQ对话。生产者部分工作正常,但消费者工作了一段时间并暂停。生产者和消费者作为不同的应用程序运行。更多关于消费者部分的信息

  • 我们将
    SimpleMessageListenerContainer
    ChannelAwareMessageListener
    一起使用,使用手动
    ack
    模式和默认
    预取(1)
  • 在我们的应用程序中,我们创建队列(按需)并将其添加到侦听器中
  • 当我们从10个
    ConcurrentConsumers
    和20个
    MaxConcurrentConsumers
    开始时,消费大约持续15个小时并暂停。当我们将
    MaxConcurrentConsumers
    增加到75时,这种情况会在1小时内发生
在RabbitMQ UI上,当出现这种情况时,我们会在通道选项卡上看到带有3/4 un
ack
ed消息的通道,在此之前,只有1条un
ack
ed消息

我们的线程转储类似于。但将心跳设置为60无助于改善这种情况

大多数线程转储都有以下消息。如果需要,我将附加整个线程转储。如果我缺少任何可能导致消费者暂停的设置,请告知我

"pool-6-thread-16" #86 prio=5 os_prio=0 tid=0x00007f4db09cb000 nid=0x3b33 waiting on condition [0x00007f4ebebec000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007b9930b68> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.LinkedBlockingQueue.put(LinkedBlockingQueue.java:350)
    at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$InternalConsumer.handleDelivery(BlockingQueueConsumer.java:660)
    at com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:144)
    at com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:99)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
“pool-6-thread-16”#86 prio=5 os_prio=0 tid=0x00007f4db09cb000 nid=0x3b33等待条件[0x00007f4ebebebec000]
java.lang.Thread.State:等待(停车)
在sun.misc.Unsafe.park(本机方法)
-停车等待(java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
位于java.util.concurrent.LinkedBlockingQueue.put(LinkedBlockingQueue.java:350)
位于org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$InternalConsumer.handleDelivery(BlockingQueueConsumer.java:660)
位于com.rabbitmq.client.impl.ConsumerDispatcher$5.run(ConsumerDispatcher.java:144)
位于com.rabbitmq.client.impl.ConsumerWorkService$WorkPoolRunnable.run(ConsumerWorkService.java:99)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
运行(Thread.java:745)
更多信息
我们动态地向SimpleMessageListenerContainer添加和删除队列,我们怀疑这会导致一些问题,因为每次我们从侦听器添加或删除队列时,所有BlockingQueueConsumer都会被删除并再次创建。您认为这是否会导致此问题?

您的问题在目标侦听器的下游某个位置

看,
预取(1)
导致:

this.queue = new LinkedBlockingQueue<Delivery>(prefetchCount);

对,锁定驻车。

您的问题在目标侦听器的下游某处

看,
预取(1)
导致:

this.queue = new LinkedBlockingQueue<Delivery>(prefetchCount);

右侧,锁定驻车。

AMQP-621现在合并为主控;我们将在未来几天发布1.6.1.release。

AMQP-621现在合并为master;我们将在未来几天发布1.6.1.release。

您需要在某个地方发布完整的线程转储,可能不会在这里发布,因为它太大了;可能是pastebin或github之类的东西。容器线程很可能被卡在代码中的某个地方。@GaryRussell:是包含完整线程转储的粘贴箱。线程转储看起来不错-所有容器线程都在
nextMessage()中等待
看来你当前的理论是正确的——网络中的某些东西悄悄地中断了连接——一些路由器为空闲连接这样做。设置所请求的心跳应该可以保持连接的活动状态-您需要使用网络监视器(tcpdump、wireshark等)来解决此问题。@GaryRussell:我们尝试使用心跳选项,但没有任何用处(尽管我们没有尝试使用任何网络监视器),而且我们也没有空闲连接—我们不断有流量。我已经为这个问题添加了更多的信息,我们认为这可能是原因。嗯,这是一种可能性,你问题中的线索试图插入一条信息;看起来队列已满,但可能旧的消费者已经离开了-这不应该发生,因为我们在停止消费者之前取消了它,但可能存在竞争条件。请打开一个,我们来看看。你需要将完整的线程转储发布到某个地方,可能不是在这里,因为它太大了;可能是pastebin或github之类的东西。容器线程很可能被卡在代码中的某个地方。@GaryRussell:是包含完整线程转储的粘贴箱。线程转储看起来不错-所有容器线程都在
nextMessage()中等待
看来你当前的理论是正确的——网络中的某些东西悄悄地中断了连接——一些路由器为空闲连接这样做。设置所请求的心跳应该可以保持连接的活动状态-您需要使用网络监视器(tcpdump、wireshark等)来解决此问题。@GaryRussell:我们尝试使用心跳选项,但没有任何用处(尽管我们没有尝试使用任何网络监视器),而且我们也没有空闲连接—我们不断有流量。我已经为这个问题添加了更多的信息,我们认为这可能是原因。嗯,这是一种可能性,你问题中的线索试图插入一条信息;看起来队列已满,但可能旧的消费者已经离开了-这不应该发生,因为我们在停止消费者之前取消了它,但可能存在竞争条件。请打开一个盒子,我们来看看。