今天项目遇到一个问题,同一个应用中,需要消费不同的vhost中不同queue的消息,目前只实现了multi consumer,如果还需要向不同的集群或vhost发消息,那么应该需要配置不同的RabbitAdmin,不知道有没有坑。
rabbit的大概配置如下:
1. 起初项目只需要监听一个vhost中的queue,所以使用spring-boot-autoconfigure中的默认配置,直接在config文件中配置:
spring.rabbitmq.host = mq-demo.sl.com
spring.rabbitmq.password = dangerous
spring.rabbitmq.port = 5672
spring.rabbitmq.username = admin
spring.rabbitmq.virtual-host = /msgbu
在rabbit的config文件中,只需要设置一下messageconverter即可,代码如下:
@Configuration
@ComponentScan
@Slf4j
public class RabbitMqConfig {
@Bean(name = "xxxListenerContainer")
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactoryPlus(
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory,
Jackson2JsonMessageConverter jackson2JsonMessageConverter) {
rabbitListenerContainerFactory.setMessageConverter(jackson2JsonMessageConverter);
return rabbitListenerContainerFactory;
}
@Bean
public Jackson2JsonMessageConverter jackson2JsonMessageConverter(ObjectMapper xssObjectMapper) {
return new Jackson2JsonMessageConverter(xssObjectMapper);
}
}
然后在listener中直接加一个@RabbitListener注解,指定containerFactory和queue即可。(这里如果已经bind了,可以不指定bindings)
@RabbitListener(containerFactory = "xxLlistenerContainer",
bindings = @QueueBinding(value = @Queue(value = "xxQueue"E, durable = "true"),
exchange = @Exchange(value = “xxexchange”, durable = "true"),
key = "xxRoutingKey"))
public void processInvoice(ProcessMessage processMessage)
2. 现在需要增加一个vhost的queue,一开始我以为不能继续使用这种默认注入的方式,就在spring boot的application中,增加了@SpringBootApplication(exclude = {RabbitAutoConfiguration.class})
@Slf4j
@EnableMbean
@EnableConfigCenter
@SpringBootApplication(exclude = {RabbitAutoConfiguration.class})
public class ApiApplication {
但是发现启动不成功,因为进入RabbitAutoConfiguration.java会发现他还会加载很多其他的东西,所以仍然需要使用。只需要更改:
(1)在RabbitMqConfig上加@EnableRabbit和@EnableConfigurationProperties(RabbitProperties.class)注解,EnableConfigurationProperties是为了引入配置rabbitProperties。
@Slf4j
@Configuration
@ComponentScan
@EnableRabbit
@EnableConfigurationProperties(RabbitProperties.class)
public class RabbitMqConfig {
@Value("${spring.rabbitmq.virtual-host2}")
private String virtualHost2;
@Autowired
private RabbitProperties rabbitProperties;
//【START】default mq config
@Bean
@Primary
public ConnectionFactory connectionFactory() {
return this.buildConnectionFactory(rabbitProperties.getHost(), rabbitProperties.getPort(),
rabbitProperties.getUsername(), rabbitProperties.getPassword(), rabbitProperties.getVirtualHost());
}
@Bean
@Primary
public SimpleRabbitListenerContainerFactory listenerContainerFactory(
@Qualifier("connectionFactory") ConnectionFactory connectionFactory,
@Qualifier("jackson2JsonMessageConverter") Jackson2JsonMessageConverter jackson2JsonMessageConverter) {
return this.buildSimpleRabbitListenerContainerFactory(connectionFactory, jackson2JsonMessageConverter);
}
@Bean
@Primary
public RabbitTemplate rabbitTemplate(
@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
@Bean
@Primary
public AmqpAdmin amqpAdmin(@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
//【END】default mq config
@Bean
public ConnectionFactory featureConnectionFactory() {
return this.buildConnectionFactory(rabbitProperties.getHost(), rabbitProperties.getPort(),
rabbitProperties.getUsername(), rabbitProperties.getPassword(), featureVirtualHost);
}
@Bean
public SimpleRabbitListenerContainerFactory featureListenerContainerFactory(
@Qualifier("featureConnectionFactory") ConnectionFactory connectionFactory,
@Qualifier("jackson2JsonMessageConverter") Jackson2JsonMessageConverter jackson2JsonMessageConverter) {
return this.buildSimpleRabbitListenerContainerFactory(connectionFactory, jackson2JsonMessageConverter);
}
@Bean(name = "featureRabbitTemplate")
public RabbitTemplate featureRabbitTemplate(
@Qualifier("featureConnectionFactory") ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
@Bean
public AmqpAdmin featureAmqpAdmin(@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
private ConnectionFactory buildConnectionFactory(String host, int port, String username, String password,
String virtualHost) {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost(host);
connectionFactory.setPort(port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
return connectionFactory;
}
private SimpleRabbitListenerContainerFactory buildSimpleRabbitListenerContainerFactory(
ConnectionFactory connectionFactory, Jackson2JsonMessageConverter jackson2JsonMessageConverter) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(jackson2JsonMessageConverter);
factory.setMaxConcurrentConsumers(5);
return factory;
}
只需要根据自定义rabbitProperties中的第二个vhost,另外定义featureConnectionFactory以及featureListenerContainerFactory。(2). 对于默认的default rabbit listener,containerfactory指定为listenerContainerFactory(可以自定义名称,比如featureListenerContainer2;不过如果去掉autoconfiguration,那么必须指定为这个名字,否则会抛异常),对于另外的listener,指定RabbitMqConfig中相应的containerFactory,这里是featureListenerContainerFactory。