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的 ...
随机推荐
- Elasticsearch-head插件的安装与配置
第一种: 通过浏览器添加插件 通过chrome安装插件的方式提供一个可操作es的图形化界面. 在chrome 浏览器中,通过"扩展程序" 添加 elasticsearch head ...
- JetBrains 系列软件汉化包 2017.3-2018.1
JetBrains 系列软件汉化包 关键字: Android Studio 3.0-3.1.3 汉化包 CLion 2018.1-2018.2 汉化包 GoLand 2017.3.2-2018.2 汉 ...
- RE Validation in JavaEE
以下是关于RE校验的一些方法的基本功能: import java.util.regex.Pattern;<br> /** * 校验器:利用正则表达式校验邮箱.手机号等 * */<br ...
- VSCode Remote-SSH 连接服务器
- 学习PHP中的iconv扩展相关函数
想必 iconv 这个扩展的相关函数大家多少都接触过,做为 PHP 的默认扩展它已经存在了很久,也是我们在操作字符编码时经常会使用的函数.不过除了 iconv() 这个函数外,你还知道它的其它函数吗? ...
- PHP中的PDO操作学习(三)预处理类及绑定数据
要说 PDO 中最强大的功能,除了为不同的数据库提供了统一的接口之外,更重要的就是它的预处理能力,也就是 PDOStatement 所提供的功能.因为它的存在,才让我们可以安心地去使用而不用操心 SQ ...
- 使用fiddler抓包模拟器及配置fiddler过滤
一. 安装fiddler https://www.telerik.com/fiddler 二. 配置fiddler,一下的ip要根据自己电脑情况设置 然后重启Fiddler,一定要重启!!! 三.配置 ...
- EcShop调用显示指定分类下的子分类方法
ECSHOP首页默认的只有全部分类,还有循环大类以及下面小类的代码,貌似没有可以调用显示指定大类下的子分类代码.于是就有这个文章的产生了,下面由夏日博客来总结下网站建设过程中ECSHOP此类问题的网络 ...
- Jmeter系列(6)- 分析源码,创建登录、浏览商品接口请求
前言简介 接口的压力测试有个二八原则:线上80%的用户量在一天24小时20%(即4.8个小时)的时间里可以平稳运行,这个接口就算是通过压力测试了 源码分析 登录 浏览商品 创建请求 登录 浏览菜单 C ...
- LR11自带网站
LR自带的飞机订票系统 启动服务:安装路径\HP\LoadRunner\WebTours下的StartServer.bat 打开网页:地址 http://127.0.0.1:1080/WebTour ...