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的 ...
随机推荐
- OSS对象存储的文件上传、解冻、下载与查看
上传文件 cp命令用于上传.下载.拷贝文件. # 语法 ./ossutil cp [-r] file_url cloud_url # 例如 ossutil64 cp -r /remote/closed ...
- 剑指 Offer 60. n个骰子的点数
剑指 Offer 60. n个骰子的点数 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率. 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n ...
- HDU1548 Building Roads
A strange lift Description There is a strange lift.The lift can stop can at every floor as you want, ...
- 关于 CLAHE 的理解及实现
CLAHE CLAHE 是一种非常有效的直方图均衡算法, 目前网上已经有很多文章进行了说明, 这里说一下自己的理解. CLAHE是怎么来的 直方图均衡是一种简单快速的图像增强方法, 其原理和实现过程以 ...
- Thinkphp5 主动式 计划任务 支持windows和linux
百度搜索过相关的php计划任务的资料,特别是搜索thinkphp的计划任务,目前能明确实现的都是被动式的,就是通过tp3.2自带的计划任务类实现,通过挂钩子的形式,用户访问网站的时候就执行计划任务,这 ...
- requests入门大全
02 requests接口测试-requests的安装 安装常见问题 提示连接不上,443问题 一般是因为浏览器设置了代理,关闭代理. 网络加载慢,设置国内镜像地址 1.pip安装 2.pycharm ...
- adb devices如何连逍遥模拟器的设备
adb device连接真机,上一篇已经讲过了,这篇讲如何连接模拟器.这里我用的模拟器逍遥模拟器.我先插上手机,另外启动了一个模拟器,直接在cmd中输入adb devices,按理应该有2个设备id, ...
- P4357-[CQOI2016]K远点对【K-Dtree】
正题 题目链接:https://www.luogu.com.cn/problem/P4357 题目大意 平面上给出\(n\)个点,求第\(k\)远的点对距离. 解题思路 \(\text{K-Dtree ...
- Golang使用swaggo自动生成Restful API文档
#关于Swaggo 相信很多程序猿和我一样不喜欢写API文档.写代码多舒服,写文档不仅要花费大量的时间,有时候还不能做到面面具全.但API文档是必不可少的,相信其重要性就不用我说了,一份含糊的文档甚至 ...
- Unity 刚体问题 解决相互作用力
在进行开发过程中,当两个都具有碰撞体和刚体的 游戏物体进行接触之后,或多或少都会出现相互作用力,对于体验有一定的影响. 需要在FixedUpdate(间隔固定的时间调用,不受游戏帧率的影响) 当中 ...