• Springboot配置多数据源Rabbitmq


      在上一篇我们提到了如何在Springboot项目中搭建单个Rabbitmq,但是当我们遇到多数据源Rabbitmq的时候,需要怎么做呢?

      我们首先看application.yml文件

    spring:
      rabbitmq:
        rabbitmq:
        cart-order:
          virtual-host: /
          host: localhost
          port: 5672
          username: guest
          password: guest
        order-adaptor:
          virtual-host: /
          host: localhost
          port: 5672
          username: test
          password: 123456  
        listener:
          simple:
            concurrency: 10
            max-concurrency: 20
            prefetch: 5
    
    mq:
      env: test
    
    cart:
      place:
        order:
          queue: ${mq.env}.cart.place.order.queue
          exchange: ${mq.env}.cart.place.order.exchange
          routing:
            key: ${mq.env}.cart.place.order.routing.key  
    
    ticketing:
      place:
        order:
          queue: ${mq.env}.ticketing.place.order.queue
          exchange: ${mq.env}.ticketing.place.order.exchange
          routing:
            key: ${mq.env}.ticketing.place.order.routing.key  

    然后主要修改的部分还是在RabbitmqConfig的修改

    @Configuration
    public class RabbitmqConfig {
        private static final Logger logger = LogManager.getLogger(RabbitmqConfig.class);
    
        @Autowired
        private Environment environment;
    
        @Autowired
        private SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer;
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Bean(name = "cartOrderCachingConnectionFactory")
        @Primary
        public CachingConnectionFactory cartOrderCachingConnectionFactory() {
            CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
            cachingConnectionFactory.setHost(environment.getProperty("spring.rabbitmq.cart-order.host"));
            cachingConnectionFactory.setPort(environment.getProperty("spring.rabbitmq.cart-order.port", int.class));
            cachingConnectionFactory.setUsername(environment.getProperty("spring.rabbitmq.cart-order.username"));
            cachingConnectionFactory.setPassword(environment.getProperty("spring.rabbitmq.cart-order.password"));
            cachingConnectionFactory.setVirtualHost(environment.getProperty("spring.rabbitmq.cart-order.virtual-host"));
            cachingConnectionFactory.setPublisherReturns(true);
            cachingConnectionFactory.setPublisherConfirms(true);
            return cachingConnectionFactory;
        }
    
        @Bean(name = "orderAdaptorCachingConnectionFactory")
        public CachingConnectionFactory orderAdaptorCachingConnectionFactory() {
            CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
            cachingConnectionFactory.setHost(environment.getProperty("spring.rabbitmq.order-adaptor.host"));
            cachingConnectionFactory.setPort(environment.getProperty("spring.rabbitmq.order-adaptor.port", int.class));
            cachingConnectionFactory.setUsername(environment.getProperty("spring.rabbitmq.order-adaptor.username"));
            cachingConnectionFactory.setPassword(environment.getProperty("spring.rabbitmq.order-adaptor.password"));
            cachingConnectionFactory.setVirtualHost(environment.getProperty("spring.rabbitmq.order-adaptor.virtual-host"));
            cachingConnectionFactory.setPublisherReturns(true);
            cachingConnectionFactory.setPublisherConfirms(true);
            return cachingConnectionFactory;
        }
    
        /**
         * singleton can't set multi times callback
         * @return
         */
        @Bean(name = "cartOrderRabbitTemplate")
        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        @Primary
        public RabbitTemplate cartOrderRabbitTemplate(@Qualifier("cartOrderCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
    
           RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
           rabbitTemplate.setMandatory(true);
           rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
    
           rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
               if (ack) {
                   logger.info("cartOrder message send succeed:correlationData({}),ack({}),cause({})",correlationData, ack, cause);
               } else {
                   logger.info("cartOrder message send failed:correlationData({}),ack({}),cause({})",correlationData, ack, cause);
               }
           });
    
    
           rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
               logger.info("cartOrder message lose:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey, replyCode, replyText, message);
           });
    
           return rabbitTemplate;
    
        }
    
        /**
         * singleton can't set multi times callback
         * @return
         */
        @Bean(name = "orderAdaptorRabbitTemplate")
        @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
        public RabbitTemplate orderAdaptorRabbitTemplate(@Qualifier("orderAdaptorCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
    
            RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
            rabbitTemplate.setMandatory(true);
            rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
            rabbitTemplate.setRoutingKey("");
            rabbitTemplate.setDefaultReceiveQueue("");
    
            rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
                if (ack) {
                    logger.info("orderAdaptor message send succeed:correlationData({}),ack({}),cause({})",correlationData, ack, cause);
                } else {
                    logger.info("orderAdaptor message send failed:correlationData({}),ack({}),cause({})",correlationData, ack, cause);
                }
            });
    
    
            rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
                logger.info("orderAdaptor message lose:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey, replyCode, replyText, message);
            });
    
            return rabbitTemplate;
    
        }
    
        @Bean(name = "cartOrderSingleListenerContainer")
        @Primary
        public SimpleRabbitListenerContainerFactory cartOrderSingleListenerContainer(SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer,
                                                                                     @Qualifier("cartOrderCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factory.setConnectionFactory(cachingConnectionFactory);
            factory.setMessageConverter(new Jackson2JsonMessageConverter());
            factory.setConcurrentConsumers(1);
            factory.setMaxConcurrentConsumers(1);
            factory.setPrefetchCount(1);
            factory.setTxSize(1);
            factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    
            return factory;
        }
    
        @Bean(name = "cartOrderMultiListenerContainer")
        @Primary
        public SimpleRabbitListenerContainerFactory cartOrderMultiListenerContainer(SimpleRabbitListenerContainerFactoryConfigurer factoryConfigurer,
                                                                                    @Qualifier("cartOrderCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factoryConfigurer.configure(factory, cachingConnectionFactory);
            factory.setMessageConverter(new Jackson2JsonMessageConverter());
            factory.setConcurrentConsumers(environment.getProperty("spring.rabbitmq.listener.simple.concurrency", int.class));
            factory.setMaxConcurrentConsumers(environment.getProperty("spring.rabbitmq.listener.simple.max-concurrency", int.class));
            factory.setPrefetchCount(environment.getProperty("spring.rabbitmq.listener.simple.prefetch", int.class));
    
            factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    
            return factory;
        }
    
        @Bean(name = "orderAdaptorSingleListenerContainer")
        public SimpleRabbitListenerContainerFactory orderAdaptorSingleListenerContainer(@Qualifier("orderAdaptorCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factory.setConnectionFactory(cachingConnectionFactory);
            factory.setMessageConverter(new Jackson2JsonMessageConverter());
            factory.setConcurrentConsumers(1);
            factory.setMaxConcurrentConsumers(1);
            factory.setPrefetchCount(1);
            factory.setTxSize(1);
            factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    
            return factory;
        }
    
        @Bean(name = "orderAdaptorMultiListenerContainer")
        public SimpleRabbitListenerContainerFactory orderAdaptorMultiListenerContainer(@Qualifier("orderAdaptorCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
            SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
            factoryConfigurer.configure(factory, cachingConnectionFactory);
            factory.setMessageConverter(new Jackson2JsonMessageConverter());
            factory.setConcurrentConsumers(environment.getProperty("spring.rabbitmq.listener.simple.concurrency", int.class));
            factory.setMaxConcurrentConsumers(environment.getProperty("spring.rabbitmq.listener.simple.max-concurrency", int.class));
            factory.setPrefetchCount(environment.getProperty("spring.rabbitmq.listener.simple.prefetch", int.class));
    
            factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    
            return factory;
        }
    
        /**
         * Message persistent: Set the deliveryMode of the message to 2 and the consumer can continue to consume
         * the messages after persistence after restarting;
         * Use convertAndSend to send a message. The message is persistent by default. The following is the source code:
         * new MessageProperties() --> DEFAULT_DELIVERY_MODE = MessageDeliveryMode.PERSISTENT --> deliveryMode = 2;
         *
         * @param exchangeName
         * @param routingKeyName
         * @param content
         * @param flag
         * @param messageId
         * @param <T>
         */
        public <T> void sendMessage(RabbitTemplate rabbitTemplate, String exchangeName, String routingKeyName, T content, boolean flag, String messageId) {
            logger.info("message send :messageId({}), exchangeName({}), routingKeyName({}), content({}), flag({})",
                    messageId, exchangeName, routingKeyName, content);
    
            CorrelationData correlationData = new CorrelationData();
            MessageProperties properties = new MessageProperties();
            properties.setContentType("application/json");
    
            try {
                if (flag) {
                    properties.setCorrelationId(messageId);
                    correlationData.setId(messageId);
    
                    rabbitTemplate.convertAndSend(exchangeName,
                            routingKeyName,
                            MessageBuilder.withBody(objectMapper.writeValueAsBytes(content)).andProperties(properties).build(),
                            correlationData);
                } else {
                    rabbitTemplate.convertAndSend(exchangeName,
                            routingKeyName,
                            MessageBuilder.withBody(objectMapper.writeValueAsBytes(content)).andProperties(properties).build(),
                            correlationData);
                }
            } catch (Exception e) {
                logger.error("error message :e.getMessage({})", e.getMessage());
            }
    
        }
    
    
    }

    从代码中就可以看到我们定义了多个连接,@Primary表示我们默认的连接。因为在单个数据源的情况下,我们可以使用默认的加载方式读取到mq的配置,但是多数据源的情况下我们就必须明确的指出每个bean对应的配置详情了。但是到这一步我们仍然会出现问题,那就是我们的queue和exchange的绑定仍然是默认的。单数据源的时候我们是默认绑定到单独的mq上,现在我们需要动态的分配它们的绑定信息,所以QueueConfig方式就不能满足我们的需求了,于是我采用了RabbitAdmin这个类动态的帮助我绑定queue和exchange到指定的mq上。

    @Configuration
    public class CartOrderRabbitAdminConfig {
    
        private static final Logger logger = LogManager.getLogger(CartOrderRabbitAdminConfig.class);
    
        @Autowired
        private Environment environment;
    
        @Bean
        public RabbitAdmin cartOrderRabbitAdmin(@Qualifier("cartOrderCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
    
            RabbitAdmin rabbitAdmin = new RabbitAdmin(cachingConnectionFactory);
            rabbitAdmin.setAutoStartup(true);//place cart order
            Queue placeCartOrderQueue = RabbitmqUtil.createQueue(environment.getProperty("cart.place.order.queue"));
            DirectExchange placeCartOrderExchange = RabbitmqUtil.createExchange(environment.getProperty("cart.place.order.exchange"));
            Binding placeCartOrderBinding = RabbitmqUtil.createBinding(placeCartOrderQueue, placeCartOrderExchange, environment.getProperty("cart.place.order.routing.key"));
            RabbitmqUtil.createRabbitAdmin(placeCartOrderQueue, placeCartOrderExchange, placeCartOrderBinding, rabbitAdmin);
    
            //
    
            return rabbitAdmin;
    
        }
    @Configuration
    public class TicketOrderRabbitAdminConfig {
    
        private static final Logger logger = LogManager.getLogger(TicketOrderRabbitAdminConfig.class);
    
        @Autowired
        private Environment environment;
    
        @Bean
        public RabbitAdmin ticketOrderRabbitAdmin(@Qualifier("orderAdaptorCachingConnectionFactory")CachingConnectionFactory cachingConnectionFactory) {
    
            RabbitAdmin rabbitAdmin = new RabbitAdmin(cachingConnectionFactory);
            rabbitAdmin.setAutoStartup(true);
    
            //place ticket order
            Queue createCartOrderQueue = RabbitmqUtil.createQueue(environment.getProperty("ticketing.place.order.queue"));
            DirectExchange createCartOrderExchange = RabbitmqUtil.createExchange(environment.getProperty("ticketing.place.order.exchange"));
            Binding createCartOrderBinding = RabbitmqUtil.createBinding(createCartOrderQueue, createCartOrderExchange, environment.getProperty("ticketing.place.order.routing.key"));
            RabbitmqUtil.createRabbitAdmin(createCartOrderQueue, createCartOrderExchange, createCartOrderBinding, rabbitAdmin);
    
            return rabbitAdmin;
    
        }
    
    
    
    }
    public class RabbitmqUtil {
    
        public static DirectExchange createExchange (String exchangeName) {
            if(StringUtils.isNotBlank(exchangeName)) {
                return new DirectExchange(exchangeName, true, false);
            }
    
            return null;
    
        }
    
        public static Queue createQueue(String queueName) {
            if(StringUtils.isNotBlank(queueName)) {
                return new Queue(queueName, true);
            }
    
            return null;
        }
    
        public static Binding createBinding (Queue queueName, DirectExchange exchangeName, String routingKeyName) {
            if(Objects.nonNull(queueName) && Objects.nonNull(exchangeName) && StringUtils.isNotBlank(routingKeyName)) {
                return BindingBuilder.bind(queueName).to(exchangeName).with(routingKeyName);
            }
            return null;
        }
    
        public static void createRabbitAdmin(Queue queue, DirectExchange exchange, Binding binding, RabbitAdmin rabbitAdmin) {
            rabbitAdmin.declareQueue(queue);
            rabbitAdmin.declareExchange(exchange);
            rabbitAdmin.declareBinding(binding);
        }
    }

    如上,我们就可以就可以动态绑定我们queue和exchange到目标mq上了,生产者和消费者和单数据源的情况下没有很大的区别。

  • 相关阅读:
    2021昆明站K-Riichi!!(麻将)
    数据结构 Week 3 --- dsu on tree 和 点分治
    数据结构 Week 2 --- 平衡树
    数据结构 Week 1 --- 从线段树到主席树
    一些思维题(三)
    一些思维题(二)
    2021ICPC昆明站总结及补题
    2021ICPC昆明M题 非主席树做法
    2020ICPC昆明参赛
    记5.28leetcode简单题
  • 原文地址:https://www.cnblogs.com/daishoucheng/p/12022451.html
Copyright © 2020-2023  润新知