RabbitMQ消息队列学习笔记

参考文章

一、RabbitMQ架构组成

  • Broker
    RabbitMQ服务本身,接收和分发消息

  • Virtual Host
    出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQ server 提供的服务时,可以划分出多个 vhost,每个用户在自己的 vhost 创建 exchange 或 queue 等。

  • Connection
    连接,生产者或消费者和RabbitMQ之间的TCP网络连接

  • Channel
    Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个 thread 创建单独的 channel 进行通讯,AMQP method 包含了 channel id 帮助客户端和 message broker 识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的Connection 极大减少了操作系统建立 TCP connection 的开销

  • Message
    消息

  • Exchange
    交换机,是 message 到达 broker 的第一站,用于根据分发规则、匹配查询表中的 routing key,分发消息到 queue 中去,不具备消息存储的功能。常用的类型有:direct、topic、fanout

    1. direct
    • 工作原理:direct Exchange 根据消息的路由键(routing key)将消息路由到与之匹配的队列。
    • 特点:
      • 精确匹配:只有当消息的路由键与队列绑定的路由键完全匹配时,消息才会被路由到该队列。
- 一对一或多对一:一个队列可以绑定多个路由键,从而接收多个消息;但一个消息只能被路由到一个队列。
  • 用途:适用于需要精确匹配和分发消息的场景,例如根据特定的条件将消息发送到不同的处理程序。
  1. topic
  • 工作原理:topic Exchange 根据消息的路由键与队列绑定的模式进行匹配。模式可以包含通配符(* 和 #),用于匹配多个路由键。
  • 特点:
    • 模糊匹配:可以使用通配符来匹配多个路由键,提供了更灵活的路由方式。
    • 一对多或多对多:一个队列可以绑定多个模式,从而接收多个消息;一个消息也可以被路由到多个队列。
  • 用途:适用于需要根据主题或模式进行消息分发的场景,例如根据消息的主题将其发送到不同的订阅者。
  1. **fanout:
  • 工作原理:fanout Exchange 将消息广播到所有与之绑定的队列,而不考虑消息的路由键。
  • 特点:
    • 广播模式:所有绑定到 fanout Exchange 的队列都会收到相同的消息。
    • 一对多:一个消息可以被广播到多个队列。
  • 用途:适用于需要将消息广播到多个消费者的场景,例如实时通知、日志记录等。
  • Bindings
    exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key,Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据。

  • Routing key
    是一个路由规则,虚拟机可以用它来确定如何路由一个特定消息

  • Queue
    消息队列,保存消息并将它们转发给消费者进行消费。

二、四大核心概念

  • 生产者
    产生数据发送消息的程序是生产者

  • 交换机
    首先它接收来自生产者的消息,然后它按照不同的策略将消息推送到队列中。在交换机中可以配置不同的发送策略,比如简单的一对一消息发送和接收(类似于写信),可以配置只转发给一个队列,该队列只有一个消费者程序处理消息。或者是一对多的策略(电商网站),电商网站用户下订单后,订单服务会将顾客订单的消息发送到一个交换机中,这个交换机绑定了物流服务、支付服务等其他服务,这样各个服务都能收到这个订单消息做自己的事情,比如物流服务去给订单发货,支付服务收顾客的钱。

  • 队列
    队列用来连接交换机和消费者,队列是RabbitMQ内部使用的一种数据结构,本质就是一个存放消息的缓冲区

  • 消费者
    消费与接收具有相似的含义。消费者大多时候是一个等待接收消息的程序。请注意生产者,消费者和消息中间件很多时候并不在同一机器上。同一个应用程序既可以是生产者又是可以是消费者。

三、简易案例

  • 使用docker启动一个带有管理后台的RabbitMQ服务
1
2
3
4
5
#这里使用镜像站拉取带有web management页面的镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/rabbitmq:3.13.3-management
#然后启动一个容器
docker run -id --restart=always --name=rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=用户名 -e RABBITMQ_DEFAULT_PASS=密码 镜像tag或镜像id
#然后访问ip:15672端口就可以看到管理页面
  • 引入Maven依赖
1
2
3
4
5
<!--rabbitmq实现的是amqp协议-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • 生产者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public class MessageProducer {

@Autowried
private RabbitTemplate rabbitTemplate;

public void sendMessage(String message) {
//RabbitTemplate提供了很多重载方法区发送消息
rabbitTemplate.convertAndSend("queue01", message);
}

@Scheduled(cron = "*/10 * * * * ?")
public void send() {
//这里通过定时任务每10发送一次消息
sendMessage("现在时间是:" + LocalDateTime.now());
}
}
  • 消费者
1
2
3
4
5
6
7
8
@Component
public class MessageConsumer {

@RabbitListener(queues = "queue01") //重要,这个注解用于指定获取消息的队列
public void receiveMessage(String message) {
System.out.println("我假装我是物流系统:Received message: " + message);
}
}

RabbitMQ消息队列学习笔记
http://blog.jingxiang.ltd/2024/07/26/RabbitMQ消息队列学习笔记/
作者
yemangran
发布于
2024年7月26日
许可协议