rabbitmq客户端在尝试声明队列时挂起

pu3pd22g  于 2022-12-13  发布在  RabbitMQ
关注(0)|答案(2)|浏览(192)

我试图寻找我的问题的解决方案,但找不到它堆栈溢出。

问题当用户尝试声明队列或交换时,在RabbitMQ服务器出现问题的极端情况下,客户端会保持等待,而不会出现任何超时,这会导致调用rabbitmq的线程始终处于等待状态(等待永不结束)。

下面是堆栈跟踪

java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.rabbitmq.utility.BlockingCell.get(BlockingCell.java:50)
    - locked <0x00000007bb0464c8> (a com.rabbitmq.utility.BlockingValueOrException)
    at com.rabbitmq.utility.BlockingCell.uninterruptibleGet(BlockingCell.java:89)
    - locked <0x00000007bb0464c8> (a com.rabbitmq.utility.BlockingValueOrException)
    at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
    at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:343)
    at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:216)
    at 
(AMQChannel.java:118)
    at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:833)
    at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler.invoke(CachingConnectionFactory.java:917)
    - locked <0x00000007bb555300> (a java.lang.Object)
    at com.sun.proxy.$Proxy293.queueDeclare(Unknown Source)
    at org.springframework.amqp.rabbit.core.RabbitAdmin.declareQueues(RabbitAdmin.java:575)
    at org.springframework.amqp.rabbit.core.RabbitAdmin.access$200(RabbitAdmin.java:66)
    at org.springframework.amqp.rabbit.core.RabbitAdmin$12.doInRabbit(RabbitAdmin.java:504)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1456)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1412)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1388)
    at org.springframework.amqp.rabbit.core.RabbitAdmin.initialize(RabbitAdmin.java:500)
    at org.springframework.amqp.rabbit.core.RabbitAdmin$11.onCreate(RabbitAdmin.java:419)
    at org.springframework.amqp.rabbit.connection.CompositeConnectionListener.onCreate(CompositeConnectionListener.java:33)
    at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:553)
    - locked <0x00000007bb057828> (a java.lang.Object)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1431)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1412)
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1388)
    at org.springframework.amqp.rabbit.core.RabbitAdmin.declareQueue(RabbitAdmin.java:207)

任何帮助都将不胜感激。队列的声明目前在我的bean的postconstruct中调用我们处理消息的组件,因此不允许任何新的bean创建。

更新这个问题在我们的产品服务器上再次出现。当尝试直接通过amqp-client-3.4.2连接时,它似乎可以工作。但是从spring-rabbit-1.6.7.RELEASE,spring-amqp-1.6.7.RELEASE它不能工作。

通过amqp客户端-3.4.2

ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("<<HOST NAME>>");
        factory.setUsername("<<USERNAME>>");
        factory.setPassword("<<PASSWORD>>");
        factory.setVirtualHost("<<VIRTUAL HOST>>");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);

Code flow with rabbit-amqp client
不工作的Spring方式

CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setHost("<<HOST NAME>>");
        factory.setUsername("<<USERNAME>>");
        factory.setPassword("<<PASSWORD>>");
        factory.setVirtualHost("<<VIRTUAL HOST>>");

        RabbitAdmin admin = new RabbitAdmin(factory);
        Queue queue = new Queue(QUEUE_NAME);
        admin.declareQueue(queue);

Code flow with spring amqp
这个问题很少发生,我们仍在试图找出此行为背后的原因。我们尝试设置连接超时,但在我们的测试程序中不起作用。
在进一步调试时,看起来像是一个异常没有让通知发送回我们的代码。对于客户端未找到这类问题,我们正确地获得了异常。
我们在CentOS Linux 7(内核)上使用RabbitMQ 3.6.10和Erlang 19.3.4

fjnneemd

fjnneemd1#

队列声明当前在我的bean构造后中
我不能说挂起,但你永远不应该与代理从后构造,afterPropertiesSet()等,这是太早的应用程序上下文生命周期。
有几种变通办法-实现SmartLifecycle;从isAutoStartup()返回true,并将bean置于早期阶段(请参见Phased)。start()将在完全创建应用程序上下文后调用。
然而,通常最好将队列、绑定等定义为bean,并让框架为您完成所有声明。

h43kikqp

h43kikqp2#

我也有过类似的经历,我会分享给大家,以防对大家有所帮助。
在我看来,对“rabbitAdmin.declareQueue”的调用将等待任何正在进行的发布者确认回调完成。我在任何地方都找不到这方面的文档,但这是我目睹的行为。
在我的例子中,一个单独的线程(线程#2)正在处理一个发布者确认,而线程#1正在试图声明一个队列(并挂起)。线程#1正在等待线程#2完成,但在我的例子中,由于我正在做的一些奇怪的数据库锁定,实际上导致线程#2也在等待线程#1完成,因此出现了死锁。
我的解决方案是停止在发布者确认回调中进行重要的处理。在我的回调中,我实际上只是启动 * 又一个 * 线程来进行真实的的处理。这使得我的发布者确认回调几乎立即返回,释放任何潜在的死锁。

相关问题