Rabbitmq踩过的坑之获取不到配置文件参数

记录一条踩得坑,rabbitmq创建连接是时候希望通过配置文件管理连接地址,但是在配置类中获取不到配置文件参数

刚开始在网上找到如下代码所示创建连接的方法,但是获取不到地址、端口、用户名、密码

@Configuration
public class QueueConfig {

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Value("${mq.rabbit.address}")
    String address;
    @Value("${mq.rabbit.username}")
    String username;
    @Value("${mq.rabbit.password}")
    String password;
    @Value("${mq.rabbit.virtualHost}")
    String mqRabbitVirtualHost;

    创建mq连接
    @Bean(name = "connectionFactory")
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(mqRabbitVirtualHost);
        connectionFactory.setPublisherConfirms(true);
        //该方法配置多个host,在当前连接host down掉的时候会自动去重连后面的host

        connectionFactory.setAddresses(address);
        return connectionFactory;
    }
}

查询发现@value读取单个属性,且不支持复杂类型。

(1)@Value(“#{configProperties[‘key’]}”)

(2)@Value(“${key}”)

@Component
public class Student{
    @Value("${student.name}")
    String name;
    @Value("${student.age}")
    int age;
}

@ConfigurationProperties支持批量注入文件属性

@ConfigurationProperties("spring.datasource.druid.second")

例如:@ConfigurationProperties(“student.dog.name”)是获取单个属性

@ConfigurationProperties(prefix = “student”)读取以student开头的多个属性,配置文件如下:

student:
  name: zhang
  age: 25
  boss: true
  birth: 1998/6/15
  maps: {key1:value1,key2:value2}
  list: [1,2,3,4,5]
  dog:
    name: 旺财
    age: ${random.int[20]}

具体的@Value和@ConfigurationProperties的区别参考博客:

https://www.jianshu.com/p/82fe2a00a124

接着尝试使用@ConfigurationProperties来获取配置文件的属性,依然获取不到,都是null,想到是不是加载顺序的问题?这个猜想目前没有验证。最后通过使用类加载器来加载配置文件,创建一个rabbitmq.properties文件,配置rabbitmq服务连接地址、端口、用户名等信息,然后加载该文件获取。创建一个工具类去获取连接地址,代码如下:

public class RabbitmqUtils {
    public static String addresses = null;
    public static int port = 0;
    public static String username = null;
    public static String password = null;
    static {
             //创建配置文件对象
            Properties properties = new Properties();
//            //使用类加载器 加载配置文件
//            //获取class文件
//            Class cls = RedisUtils.class;
//            //获取类加载器
//            ClassLoader classLoader = cls.getClassLoader();
//            //加载配置文件
//            InputStream is = classLoader.getResourceAsStream("rabbitmq.properties");
//            //获取配置文件
//            properties.load(is);
            properties.load(RedisUtils.class.getClassLoader().getResourceAsStream("rabbitmq.properties"));
            addresses = properties.getProperty("spring.rabbitmq.addresses");
            port = Integer.parseInt(properties.getProperty("spring.rabbitmq.port"));
            username = properties.getProperty("spring.rabbitmq.username");
            password = properties.getProperty("spring.rabbitmq.password");

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

}

创建一个rabbitmq连接类,方便在其他服务连接使用

@Configuration
public class RabbitConnectionFactory {

    //创建mq连接
    @Bean(name = "connectionFactory")
    public org.springframework.amqp.rabbit.connection.ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(RabbitmqUtils.addresses);
        connectionFactory.setPort(RabbitmqUtils.port);
        connectionFactory.setUsername(RabbitmqUtils.username);
        connectionFactory.setPassword(RabbitmqUtils.password);
        //   connectionFactory.setVirtualHost(mqRabbitVirtualHost);
        //   connectionFactory.setPublisherConfirms(true);
        //该方法配置多个host,在当前连接host down掉的时候会自动去重连后面的host


        return connectionFactory;
    }

}

此处rabbitmq连接地址有两个,host和addresses,host默认是连接本地rabbitmq服务器的地址,localhost,addresses是可以连接到指定的地址,可以配置多个地址,通过逗号分隔开。默认连接是第一个服务,第一个服务宕机后会自动连接第二个rabbitmq服务,这里有一个问题,第一个rabbitmq宕机后队列里的消息无法消费怎么办?rabbitmq的机制是当服务启动时会自动消费交换机队列里的消息,但是如果服务没有启动,此处的消息就不能及时消费。这里需要研究一下rabbitmq集群化部署数据同步问题,暂悬。这里配置多rabbitmq服务器时,用户名、密码、端口需要一致才会自动切换。

因此,为了配置多rabbitmq服务,第一个rabbitmq宕机后自动连接第二个rabbitmq服务,rabbitmq.properties配置如下:

#主机地址
spring.rabbitmq.addresses=连接地址1,连接地址2
#端口
spring.rabbitmq.port=5672
#用户名
spring.rabbitmq.username=username
#密码
spring.rabbitmq.password=password

注意,此处只有addresses可以用逗号分开写多个,且这几个服务的用户名、密码、端口、权限要完全一致,如果你把用户名、端口、密码也用逗号分开各自写,就会出现如下报错,连接登录失败,rabbitmq不会用逗号区分登陆的用户名和密码

2020-04-10 15:14:36.676 ERROR 11132 --- [io-9011-exec-28] b.common.exception.RRExceptionHandler    : com.rabbitmq.client.AuthenticationFailureException: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.

二、记录一条新坑

微服务中,例如A服务中创建了队列发送了消息,在B服务中监听,rabbitmq默认的连接是localhost,这两个服务的连接应该是同一个rabbitmq的连接,否则A连接的是一个rabbitmq服务,B服务连接的是另一个rabbitmq服务,就会出现监听不到消息的情况。

A服务启动后控制台会打印rabbitmq连接信息如下:

2020-04-10 13:48:46.904  INFO 14940 --- [cTaskExecutor-1] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [连接地址1, 连接地址2]

B服务启动后控制台打印连接信息如下:

2020-04-10 13:48:46.904  INFO 14940 --- [cTaskExecutor-1] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [127.0.0.1]

此时只需要把上面的abbitmq连接类复制到对应服务的目录即可,服务启动时就会连接同一个rabbitmq。

rabbitmq的坑还有很多,比如消息监听失败、这个目前有一些解决方案,可以通过持久化、消息确认机制等方式来几尽可能将消息丢失率降到最低,但是不能100%保证消息完整,所以在使用时,可以酌情考虑如果对这种极低的消息丢失率可以容忍,那就可以放心的使用他,万物皆可MQ,是一个好工具。这里还有rabbitAdmin、RabbitTemplate使用上的区分以及如何动态创建绑定消息队列,后续更新。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值