springamqp 动态 Exchange Queue Failed to check/redeclare auto-delete queue(s).

Posted 烨瑗

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springamqp 动态 Exchange Queue Failed to check/redeclare auto-delete queue(s).相关的知识,希望对你有一定的参考价值。

ERROR [czx] 2023-02-04 12:15:58.188 [SimpleAsyncTaskExecutor-1] org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer:1618 - Failed to check/redeclare auto-delete queue(s).     
java.lang.NullPointerException: null
	at org.springframework.amqp.rabbit.core.RabbitAdmin.initialize(RabbitAdmin.java:496)
	at org.springframework.amqp.rabbit.core.RabbitAdmin.lambda$null$9(RabbitAdmin.java:453)
	at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:287)
	at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:164)
	at org.springframework.amqp.rabbit.core.RabbitAdmin.lambda$afterPropertiesSet$10(RabbitAdmin.java:452)
	at org.springframework.amqp.rabbit.connection.CompositeConnectionListener.onCreate(CompositeConnectionListener.java:36)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:634)
	at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:240)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1816)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1790)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1771)
	at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:345)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.redeclareElementsIfNecessary(AbstractMessageListenerContainer.java:1604)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:995)
	at java.lang.Thread.run(Thread.java:745)
WARN  [czx] 2023-02-04 12:15:58.268 [SimpleAsyncTaskExecutor-1] org.springframework.amqp.rabbit.listener.BlockingQueueConsumer:690 - Failed to declare queue: hallQueues     
WARN  [czx] 2023-02-04 12:15:58.270 [SimpleAsyncTaskExecutor-1] org.springframework.amqp.rabbit.listener.BlockingQueueConsumer:595 - Queue declaration failed; retries left=3     
org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to declare queue(s):[hallQueues]
	at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:696)
	at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.start(BlockingQueueConsumer.java:586)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:996)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: null
	at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:126)
	at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:122)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:144)
	at com.rabbitmq.client.impl.ChannelN.queueDeclarePassive(ChannelN.java:1006)
	at com.rabbitmq.client.impl.ChannelN.queueDeclarePassive(ChannelN.java:52)
	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:1032)
	at com.sun.proxy.$Proxy212.queueDeclarePassive(Unknown Source)
	at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.attemptPassiveDeclarations(BlockingQueueConsumer.java:675)
	... 3 common frames omitted
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'hallQueues' in vhost '/', class-id=50, method-id=10)
	at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
	at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
	at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:494)
	at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:288)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:138)
	... 12 common frames omitted
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'hallQueues' in vhost '/', class-id=50, method-id=10)
	at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:516)
	at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:346)
	at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:178)
	at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:111)
	at com.rabbitmq.client.impl.AMQConnection.readFrame(AMQConnection.java:670)
	at com.rabbitmq.client.impl.AMQConnection.access$300(AMQConnection.java:48)
	at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:597)
	... 1 common frames omitted

表现异常如上。

问题是 Exchange Queue 创建未成功,前提配置一切正常。

动态创建交换机、队列代码参考:springboot 整合RabbitMQ yml配置文件配置交换机 队列信息 - 官萧何 - 博客园

在 spring-boot-starter-parent 2.0.1~2.0.6 都有以上异常错误,怀疑过rabbitma 版本、依赖冲突等诸多错误,在 org.springframework.amqp.rabbit.core.RabbitAdmin.initialize 中debug 找到问题:

 

Collection<Collection> collections = this.declareCollections ? this.applicationContext.getBeansOfType(Collection.class, false, false).values() : Collections.emptyList(); 未拿到对象。
 public void initialize() 
        if (this.applicationContext == null) 
            this.logger.debug("no ApplicationContext has been set, cannot auto-declare Exchanges, Queues, and Bindings");
         else 
            this.logger.debug("Initializing declarations");
            Collection<Exchange> contextExchanges = new LinkedList(this.applicationContext.getBeansOfType(Exchange.class).values());
            Collection<Queue> contextQueues = new LinkedList(this.applicationContext.getBeansOfType(Queue.class).values());
            Collection<Binding> contextBindings = new LinkedList(this.applicationContext.getBeansOfType(Binding.class).values());
            Collection<Collection> collections = this.declareCollections ? this.applicationContext.getBeansOfType(Collection.class, false, false).values() : Collections.emptyList();
            Iterator var5 = ((Collection)collections).iterator();

解决方法:注入bean 时一定返回交换机对象

 @Bean("createExchange")
    public List<Exchange> createExchange() 
        if (rabbitMqProperties == null) 
            return null;
        
        List<ExchangeProperties> exchanges = rabbitMqProperties.getExchanges();
        List<Exchange> exchangeList = new ArrayList<>();
        if (CollUtil.isNotEmpty(exchanges)) 
            exchanges.forEach(e -> 
                // 声明交换机
                Exchange exchange = null;
                switch (e.getType()) 
                    case DIRECT:
                        exchange = new DirectExchange(e.getName());
                        break;
                    case TOPIC:
                        exchange = new TopicExchange(e.getName());
                        break;
                    case HEADERS:
                        exchange = new HeadersExchange(e.getName());
                        break;
                    case FANOUT:
                        exchange = new FanoutExchange(e.getName());
                        break;
                    case CUSTOM:
                        exchange = new CustomExchange(e.getName(), e.getCustomType(), true, false, e.getArguments());
                        break;
                    default:
                        break;
                
                // 将交换机注册到spring bean工厂 让spring实现交换机的管理
                if (exchange != null) 
                    beanFactory.registerSingleton(e.getName(), exchange);
                    exchangeList.add(exchange);
                
            );
        
        return exchangeList;// 就是这个返回解决了问题
    

 

 

以上是关于springamqp 动态 Exchange Queue Failed to check/redeclare auto-delete queue(s).的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 服务异步通信 -- 入门案例(消息预存机制)SpringAMQP发布订阅模式(FanoutExchangeDirectExchangeTopicExchange)消息转换器

Spring AMQP杂记之Spring实现简述

Exchange 2010 获取动态通讯组的成员

Exchange Server 2016管理系列课件24.管理动态通讯组

SpringAMQP

使用 Exchange 命令行管理程序查看动态通讯组的成员