SpringBoot整合多个RabbitMQ
一、背景
最近项目中需要用到了RabbitMQ来监听消息队列,监听的消息队列的 虚拟主机(virtualHost)和队列名(queueName)是不一致的,但是接收到的消息格式相同的。而且可能还存在程序不停机的情况下,动态的增加新的队列(queue)的监听,因此就需要我们自己在程序中实现一种方法实现动态配置RabbitMQ。
二、需求
我们有2个RabbitMQ的配置,在程序启动的时候,动态的配置好这2个RabbitMQ,实现消息的监听。
RabbitMQ的配置信息
| host | port | username | password | virtualHost | queueName |
|---|---|---|---|---|---|
| 47.101.130.164 | 5672 | rabbit-multi-01 | rabbit-multi-01 | /rabbit-multi-01 | queue-rabbit-multi-01 |
| 47.101.130.164 | 5672 | rabbit-multi-02 | rabbit-multi-02 | /rabbit-multi-02 | queue-rabbit-multi-02 |
三、实现思路
1、动态配置RabbitMQ
包括 ConnectionFactory,RabbitAdmin,RabbitTemplate,SimpleMessageListenerContainer等
2、将上方配置好的Bean注入到Spring容器中,之后可能需要用到
向Spring容器中注入Bean的方法
DefaultListableBeanFactory#registerSingleton
DefaultListableBeanFactory#registerBeanDefinition
四、实现步骤
1、引入maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2、创建RabbitProperties用来表示RabbitMQ的配置信息
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class RabbitProperties {
private String host;
private Integer port;
private String username;
private String password;
private String virtualHost;
private String queueName;
}
3、配置RabbitMQ
配置 ConnectionFactory,RabbitAdmin,RabbitTemplate,SimpleMessageListenerContainer等,并动态注入到Spring容器中
@Configuration
@RequiredArgsConstructor
@Slf4j
public class MultiRabbitMqConfig {
private final DefaultListableBeanFactory defaultListableBeanFactory;
private static Map<String, RabbitProperties> multiMqPropertiesMap = new HashMap<String, RabbitProperties>() {
{
put("first", RabbitProperties.builder()
.host("47.101.130.164")
.port(5672)
.username("rabbit-multi-01")
.password("rabbit-multi-01")
.virtualHost("/rabbit-multi-01")
.queueName("queue-rabbit-multi-01").build());
put("second", RabbitProperties.builder()
.host("47.101.130.164")
.port(5672)
.username("rabbit-multi-02")
.password("rabbit-multi-02")
.virtualHost("/rabbit-multi-02")
.queueName("queue-rabbit-multi-02").build());
}
};
@PostConstruct
public void initRabbitmq() {
multiMqPropertiesMap.forEach((key, rabbitProperties) -> {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(CachingConnectionFactory.class)
.addPropertyValue("cacheMode", CachingConnectionFactory.CacheMode.CHANNEL)
.addPropertyValue("host", rabbitProperties.getHost())
.addPropertyValue("port", rabbitProperties.getPort())
.addPropertyValue("username", rabbitProperties.getUsername())
.addPropertyValue("password", rabbitProperties.getPassword())
.addPropertyValue("virtualHost", rabbitProperties.getVirtualHost())
.getBeanDefinition();
String connectionFactoryName = String.format("%s%s", key, "ConnectionFactory");
defaultListableBeanFactory.registerBeanDefinition(connectionFactoryName, beanDefinition);
CachingConnectionFactory connectionFactory = defaultListableBeanFactory.getBean(connectionFactoryName, CachingConnectionFactory.class);
String rabbitAdminName = String.format("%s%s", key, "RabbitAdmin");
AbstractBeanDefinition rabbitAdminBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(RabbitAdmin.class)
.addConstructorArgValue(connectionFactory)
.addPropertyValue("autoStartup", true)
.getBeanDefinition();
defaultListableBeanFactory.registerBeanDefinition(rabbitAdminName, rabbitAdminBeanDefinition);
RabbitAdmin rabbitAdmin = defaultListableBeanFactory.getBean(rabbitAdminName, RabbitAdmin.class);
log.info("rabbitAdmin:[{}]", rabbitAdmin);
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
defaultListableBeanFactory.registerSingleton(String.format("%s%s", key, "RabbitTemplate"), rabbitTemplate);
SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer(connectionFactory);
// 设置监听的队列
simpleMessageListenerContainer.setQueueNames(rabbitProperties.getQueueName());
// 指定要创建的并发使用者的数量,默认值是1,当并发高时可以增加这个的数值,同时下方max的数值也要增加
simpleMessageListenerContainer.setConcurrentConsumers(3);
// 最大的并发消费者
simpleMessageListenerContainer.setMaxConcurrentConsumers(10);
// 设置是否重回队列
simpleMessageListenerContainer.setDefaultRequeueRejected(false);
// 设置签收模式
simpleMessageListenerContainer.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置非独占模式
simpleMessageListenerContainer.setExclusive(false);
// 设置consumer未被 ack 的消息个数
simpleMessageListenerContainer.setPrefetchCount(1);
// 设置消息监听器
simpleMessageListenerContainer.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
try {
log.info("============> Thread:[{}] 接收到消息:[{}] ", Thread.currentThread().getName(), new String(message.getBody()));
log.info("====>connection:[{}]", channel.getConnection());
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
log.error(e.getMessage(), e);
// 发生异常此处需要捕获到
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
});
/**
* 1、simpleMessageListenerContainer.start();
* 2、simpleMessageListenerContainer.stop();
* 3、如果后期rabbitmq 的配置是从数据库中读取,即用户在页面上添加一个配置,就动态创建这个
* 此时就需要调用 SimpleMessageListenerContainer#start 方法
*/
defaultListableBeanFactory.registerSingleton(String.format("%s%s", key, "SimpleMessageListenerContainer"), simpleMessageListenerContainer);
});
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
RabbitTemplate firstRabbitTemplate = (RabbitTemplate) defaultListableBeanFactory.getBean("firstRabbitTemplate");
firstRabbitTemplate.convertAndSend("exchange-rabbit-multi-01", "", "first queue message");
log.info("over...");
}).start();
}
}
五、实现效果

六、代码
https://gitee.com/huan1993/rabbitmq/tree/master/rabbitmq-springboot-multi
SpringBoot整合多个RabbitMQ的更多相关文章
- Springboot整合二 集成 rabbitmq
1.在application.yml文件中进行RabbitMQ的相关配置先上代码 spring: rabbitmq: host: 192168.21.11 port: username: guest ...
- RabbitMQ与SpringBoot整合
RabbitMQ SpringBoot 一.RabbitMQ的介绍 二.Direct模式 三.Topic转发模式 四.Fanout Exchange形式 原文地址: https://www.cnb ...
- springboot学习笔记-6 springboot整合RabbitMQ
一 RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿 ...
- Rabbitmq基本使用 SpringBoot整合Rabbit SpringCloud Stream+Rabbit
https://blog.csdn.net/m0_37867405/article/details/80793601 四.docker中使用rabbitmq 1. 搭建和启动 使用地址:rabbitm ...
- 【SpringBoot系列5】SpringBoot整合RabbitMQ
前言: 因为项目需要用到RabbitMQ,前几天就看了看RabbitMQ的知识,记录下SpringBoot整合RabbitMQ的过程. 给出两个网址: RabbitMQ官方教程:http://www. ...
- SpringBoot系列八:SpringBoot整合消息服务(SpringBoot 整合 ActiveMQ、SpringBoot 整合 RabbitMQ、SpringBoot 整合 Kafka)
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合消息服务 2.具体内容 对于异步消息组件在实际的应用之中会有两类: · JMS:代表作就是 ...
- SpringBoot28 RabbitMQ知识点、Docker下载RabbitMQ、SpringBoot整合RabbtiMQ
1 RabbitMQ知识点 1.1 整体架构图 消息生产者将消息投递到exchange中,exchange会以某种路由机制将生产者投递的消息路由到queue中,消息消费者再从queue中获取消息进行消 ...
- 一篇学习完rabbitmq基础知识,springboot整合rabbitmq
一 rabbitmq 介绍 MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced MessageQueue 高级消息队列协议 ...
- 【MQ中间件】RabbitMQ -- SpringBoot整合RabbitMQ(3)
1.前言说明 前面一篇博客中提到了使用原生java代码进行测试RabbitMQ实现多种交换机类型的队列场景.但是在项目中我们一般使用SpringBoot项目,而且RabbitMQ天生对于Spring的 ...
随机推荐
- 《openssl编程》:第一章基础知识
第一章 基础知识 1.1 对称算法 对称算法使用一个密钥.给定一个明文和一个密钥,加密产生密文,其长度和明文大致相同.解密时,使用读密钥与加密密钥相同. 对称算法主要有四种加密模式: (1) 电子密码 ...
- weblogic漏洞初探之CVE-2015-4852
weblogic漏洞初探之CVE-2015-4852 一.环境搭建 1. 搭建docker 这里用了vulhub的环境进行修改:https://vulhub.org/ 新建个文件夹,创建两个文件doc ...
- 基于Tensorflow + Opencv 实现CNN自定义图像分类
摘要:本篇文章主要通过Tensorflow+Opencv实现CNN自定义图像分类案例,它能解决我们现实论文或实践中的图像分类问题,并与机器学习的图像分类算法进行对比实验. 本文分享自华为云社区< ...
- 433MHZ SPI模块使用心得
最近使用了433MHZ的模块进行了一个通讯项目,选用的是SX1208模块,对接了RTOS和Linux两个操作系统,使用心得如下: 1. 首先要拿来datasheet看一遍,通揽一下它的功能.可以得到一 ...
- 一起学习PHP中GD库的使用(一)
又到了一个大家非常熟悉的库了,对于图像图形的处理来说,GD 库是 PHPer 们绕不过去的一道坎.从很早很早的 CMS 或者 Discuz 时代,各类开源软件在安装的时候就会明确地指出 GD 库是它们 ...
- Mysql将其他表中的数据更新到指定表中
update tb set tb.字段= (select 字段 from tb1 where tb.字段1 = tb1.字段1); update role set uid = (select ID ...
- dede5.7 标题长度限制修改
我们经常碰到dede标题长度不够用的问题20个字的标题有时候是真的有点短了网上也有些修改长度问题的帖子,但我发现都不完整所以写下来供大家参考下.免得浪费时间 第一步: 修改下面4处文件: dede目录 ...
- PHP 流行的框架
Aura Laravel Symphony Yii Zend php components Packagist 最好的组件: Awesome PHP https://www.yiiframework. ...
- 不关闭selinux下配置php+httpd访问KingbaseES
在不关闭selinux的情况下使httpd+php+KingbaseES正常使用1.正常设置php.apache 除了正常流程外还需要在/etc/sysconfig/httpd最后追加LD_LIBRA ...
- 关于python中的可哈希与不可哈希
可哈希:简要的说可哈希的数据类型,即不可变的数据结构(字符串str.元组tuple.对象集objects).它是一个将大体量数据转化为很小数据的过程,甚至可以仅仅是一个数字,以便我们可以用在固定的时间 ...