Spring boot 下使用RabbitMQ报错:链接拒绝和不能创建队列

做项目时使用了rabbitMQ,本地运行没有问题,可是部署到paas时就报错
主要是两个错误:1.链接拒绝 2.不能注册queue 报错如下:

**错误1**

Unable to connect Spring AMQP / Rabbit MQ : org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
**错误2**

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'task.queue.xxx' in vhost 'ffcd3756-5bbc-4cbc-8c46-01366b37cf80', class-id=50, method-id=10)
2017-08-27T17:15:39.550+08:00 [APP/0] [OUT] at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
2017-08-27T17:15:39.550+08:00 [APP/0] [OUT] at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:32)
2017-08-27T17:15:39.550+08:00 [APP/0] [OUT] at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:360)
2017-08-27T17:15:39.550+08:00 [APP/0] [OUT] at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:225)
2017-08-27T17:15:39.550+08:00 [APP/0] [OUT] at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:117)

task.queue.xxx 是我的对列名称

1. MQ配置文件

    @Configuration
    @Profile("dev")
    static class LocalConfiguration {
        @Value("${rabbitmq.queuename}")
        private String queueName;

        @Value("${rabbitmq.exchange}")
        private String queueExchange;

        @Value("${rabbitmq.routingkey}")
        private String routingkey;

        @Value("${cf.rabbit.service.name}")
        private String rabbitService;

        @Bean
        public ConnectionFactory connectionFactory() {
            CachingConnectionFactory factory = new CachingConnectionFactory();
            factory.setUsername("guest");
            factory.setPassword("guest");
            factory.setVirtualHost("test");
            factory.setHost("localhost");
            // factory.setPort(15672);
            factory.setPublisherConfirms(true);// 保证消息的事务性处理rabbitmq默认的处理方式为auto
                                                // ack,这意味着当你从消息队列取出一个消息时,ack自动发送,mq就会将消息删除。而为了保证消息的正确处理,我们需要将消息处理修改为手动确认的方式
            return factory;
        }

        // 配置接收端属性,
        @Bean
        public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
                ConnectionFactory connectionFactory) {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factory.setConnectionFactory(connectionFactory);
            // factory.setPrefetchCount(5);//这个参数设置,接收消息端,接收的最大消息数量(包括使用get、consume),一旦到达这个数量,客户端不在接收消息。0为不限制。默认值为3.
            factory.setAcknowledgeMode(AcknowledgeMode.AUTO);// 确认模式:自动,默认
            factory.setMessageConverter(new Jackson2JsonMessageConverter());// 接收端类型转化pojo,需要序列化
            return factory;
        }

        @Bean
        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        // 必须是prototype类型,不然每次回调都是最后一个内容
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
            RabbitTemplate template = new RabbitTemplate(connectionFactory);
            template.setMessageConverter(new Jackson2JsonMessageConverter());// 发送端类型转化pojo,需要序列化
            return template;
        }

        @Bean
        public Queue queue() {
            return new Queue(queueName, true);// TRUE 持久化
        }

        // TopicExchange(*、#模糊匹配routing key,routing
        // key必须包含"."),DirectExchange,FanoutExchange(无routing key概念)
        @Bean
        public TopicExchange exchange() {
            return new TopicExchange(queueExchange);
        }

        @Bean
        public Binding binding(Queue queue, TopicExchange exchange) {
            return BindingBuilder.bind(queue).to(exchange).with(routingkey);
        }
    }

2. 修改后的MQ配置文件

    @Configuration
    @Profile("dev")
    static class CloudConfiguration {

        @Value("${rabbitmq.queuename}")
        private String queueName;

        @Value("${rabbitmq.exchange}")
        private String queueExchange;

        @Value("${rabbitmq.routingkey}")
        private String routingkey;

        @Value("${cf.rabbit.service.name}")
        private String rabbitService;

        @Bean
        public ConnectionFactory connectionFactory() {
            CachingConnectionFactory factory = new CachingConnectionFactory();
            factory.setUsername("guest");
            factory.setPassword("guest");
            factory.setVirtualHost("test");
            factory.setHost("localhost");
            // factory.setPort(15672);
            factory.setPublisherConfirms(true);// 保证消息的事务性处理rabbitmq默认的处理方式为auto
                                                // ack,这意味着当你从消息队列取出一个消息时,ack自动发送,mq就会将消息删除。而为了保证消息的正确处理,我们需要将消息处理修改为手动确认的方式

            Channel channel = factory.createConnection().createChannel(false);

            // 声明queue,exchange,以及绑定
            try {
                channel.exchangeDeclare(queueExchange /* exchange名称 */, "topic"/* 类型 */);
                // durable,exclusive,autodelete
                channel.queueDeclare(queueName, true, false, false, null); // (如果没有就)创建Queue
                channel.queueBind(queueName, queueExchange, routingkey);
            } catch (Exception e) {
                log.error("mq declare queue exchange fail ", e);
            } finally {
                try {
                    channel.close();
                } catch (Exception e) {
                    log.error("mq channel close fail", e);
                }

            }
            return factory;
        }

        // 配置接收端属性,
        @Bean
        public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
                ConnectionFactory connectionFactory) {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factory.setConnectionFactory(connectionFactory);
            // factory.setPrefetchCount(5);//这个参数设置,接收消息端,接收的最大消息数量(包括使用get、consume),一旦到达这个数量,客户端不在接收消息。0为不限制。默认值为3.
            factory.setAcknowledgeMode(AcknowledgeMode.AUTO);// 确认模式:自动,默认
            factory.setMessageConverter(new Jackson2JsonMessageConverter());// 接收端类型转化pojo,需要序列化
            return factory;
        }

        @Bean
        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        // 必须是prototype类型,不然每次回调都是最后一个内容
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {

            RabbitTemplate template = new RabbitTemplate(connectionFactory);
            template.setMessageConverter(new Jackson2JsonMessageConverter());// 发送端类型转化pojo,需要序列化
            return template;
        }

测试发现是因为queue和exchange创建不成功导致的连接失败
刚开始我的解决办法是手动在rabbitMQ客户端创建queue和exchange,之后手动跟routingkey绑定,但是治标不治本,不是一个根本的解决办法,最后改了下MQ的配置文件,上2。再次运行就没有问题了。

总结:原因可能是rabbitMQ版本的问题,paas容器用的rabbitMQ版本是3.6.6,而我本地开发用的是3.6.10,不同的版本写法有可能不同
我的猜测哈~,知道根本原因的可以私密我^^

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值