概述
rabbitMQ 会做一个系列,包括:安装、基础使用、高级队列、集群。
使用环境: jdk 8
、springboot 2.4.10
常见概念:
- AMQP:高级消息队列协议,这是一个消息应用的规范。
- Broker: 接收和分发消息的应用,RabbitMQ Server 就是 Message Broker。
- Channel:Channel 作为轻量级 Connection 极大减少了操作系统建立 TCP connection 的开销。
- Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到 queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout(multicast)
- Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key,Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据。
- Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
docker 安装
使用 docker 安装测试环境,在 dockerHub 可以查找版本:https://hub.docker.com/
选择带有控制界面的 management 版本(包含web管理页面):
docker pull rabbitmq:3.9.5-management
rabbit mq 默认两个端口:
- 5672 是默认应用访问端口
- 15672 是默认控制台 Web 端口号
docker run -d --name rabbitMqDocker -p 52365:5672 -p 32512:15672 -v /usr/local/docker/rabbit:/var/lib/rabbitmq --hostname rabbitMq -e RABBITMQ_DEFAULT_VHOST=mqDocker76 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq:3.9.5-management
-
--hostname
: 主机名,RabbitMQ 的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名; -
-e
: 指定环境变量。- RABBITMQ_DEFAULT_VHOST:默认虚拟机名
- RABBITMQ_DEFAULT_USER:默认的用户名
- RABBITMQ_DEFAULT_PASS:默认用户名的密码
后续的控制台新增用户、权限细节略过。
Exchange 不同模式
准备环境,先添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
application 配置:
spring:
rabbitmq:
host: 127.0.0.1
port: 52365
username: admin
password: admin
virtual-host: mqDocker76
RabbitMQ 基本架构如下,然后开始分别测试三种模式。
Direct Exchange
直连模式基础用法,配置文件、生产、消费代码如下:
@Configuration
public class DirectRabbitConfig {
/**
* 队列 起名:directQueue
*/
@Bean
public Queue directQueue() {
// durable: 是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
// exclusive: 默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
// autoDelete: 是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
return new Queue("directQueue", true, false, false);
}
/**
* Direct交换机 起名:directExchange
*/
@Bean
DirectExchange directExchange() {
return new DirectExchange("directExchange", true, false);
}
/**
* 绑定,将队列和交换机绑定, 并设置用于匹配键:directRouting
*/
@Bean
Binding bindingDirect() {
return BindingBuilder.bind(directQueue()).to(directExchange()).with("directRouting");
}
}
@RestController
@RequestMapping
public class DirectProducer {
@Autowired
RabbitTemplate rabbitTemplate;
@GetMapping("/directMsg")
public String directMsg() {
Map<String, Object> map = new HashMap<>();
map.put("messageId", String.valueOf(UUID.randomUUID()));
map.put("data", "发送数据体" + System.currentTimeMillis());
map.put("createTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//将消息携带绑定键值:directRouting 发送到交换机 directExchange
rabbitTemplate.convertAndSend("directExchange", "directRouting", map);
return JSONObject.toJSONString(map);
}
}
@Component
@RabbitListener(queues = "directQueue")
public class DirectConsumer {
@RabbitHandler
public void process(Map<String, Object> message) {
System