目录
- 官网地址:https://www.rabbitmq.com/
- 官方文档:https://www.rabbitmq.com/getstarted.html
- 下载地址:https://www.rabbitmq.com/download.html
- Spring Starter官方文档:https://docs.spring.io/spring-amqp/docs/2.4.17/reference/html/
一、简介
1.1 背景
在介绍 RabbitMQ 之前,我们先来看下面一个电商项目的场景:
- 商品的原始数据保存在数据库中,增删改查都在数据库中完成。
- 搜索服务的数据来源是索引库(Elasticsearch),如果数据库商品发生变化,索引库数据没有实现及时更新。
- 商品详情做了页面静态处理,静态页面数据也不会随着数据库商品更新而变化。
如果我们在后台修改了商品的价格,搜索页面和商品详情页显示的依然是旧的价格,这样显然不对。该如何解决?
我们可能想到这样两个方案来实现:
- 方案1:每当后台对商品做增删改操作,同时修改索引库数据并更新静态页面。
- 方案2:搜索服务和商品页面静态化服务对外提供操作接口,后台在商品增删改后,调用接口来更新。
这两种方案都有个严重的问题:就是 代码耦合,后面服务中需要嵌入搜索和商品页面服务,违背了微服务的 独立原则
。
这时,我们就会采用另外一种解决办法,那就是 消息队列!
商品服务对商品增删改以后,无需去操作索引库和静态页面,只需向 MQ 发送一条消息(比如包含商品 id 的消息),也不需要关系消息被谁接收。搜索服务和静态页面服务监听 MQ,接收消息,然后分别取处理索引库和静态页面(根据商品 id 取更新索引库和商品详情静态页面)。
1.2 什么是消息队列?
MQ
,全称 Message Queue,即 消息队列
。消息队列是在消息传输的过程中保存消息的容器。它是典型的 生产者-消费者模型。生产者不断向消息队列中生产消息,消费者不断地从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了 生产者和消费者的解耦。
1.3 应用场景
开发中,消息队列通常有如下应用场景:
1)任务异步处理:
- 高并发环境下,将耗时的任务(如发送邮件、生成报告、大文件处理等)异步化,提高系统响应速度和吞吐量。
2)系统解耦:
- 不同的系统或服务(如:订单系统、库存系统、支付系统等)通过消息队列进行通信,减少直接依赖,增强系统的稳定性和可扩展性。
- 当一个服务升级或出现故障时,不会直接影响到其他依赖它的服务。
3)流量削峰:
- 在高峰期,将部分请求放入消息队列中暂存,避免直接冲击后端服务,保证系统的稳定运行。
- 消费者可以根据自身处理能力按需消费队列中的消息,实现平滑的负载均衡。
4)数据整合与同步:
- 在分布式系统中,使用 RabbitMQ 来实现数据的定时或定期同步。
- 多个数据源产生的数据可以通过数据队列汇聚并统一处理。
5)事件驱动架构:
- 构建事件驱动的微服务体系,通过发布和订阅特定事件来触发业务流程。
- 当某个事件发生时,发布事件到相应的消息队列,订阅该事件的消费者会自动接收到通知并执行相应操作。
6)高可用性和冗余:
- RabbitMQ 支持集群部署和镜像队列,确保在单点故障的情况下,系统仍然能够正常运行和处理消息。
7)延迟队列:
- 实现定时任务或延迟消息处理,例如:在一定时间后发送提醒、执行清理任务等。
8)API集成与回调:
- 在调用外部 API 时,可以先将请求放入消息队列,然后立即返回响应,待 API 实际处理完成后,再通过消息队列返回结果。
这些应用场景展示了
RabbitMQ
在 提高系统性能、提升系统稳定性、实现灵活架构设计 等方面的重要作用。
1.4 AMQP 和 JMS
MQ 是消息通信的模型,并发具体实现。现在实现 MQ 有两种主流方式:AMQP
、JMS
。
两者间的区别和联系如下:
- JMS 是 定义了统一的接口,来对消息操作进行统一;
AMQP 是通过 规定协议 来统一数据交互的格式。 - JMS 限定了 必须使用 Java 语言;
AMQP 只是协议,不规定实现方式,因此 是跨语言的。 - JMS 规定了 两种消息模型;
AMQP 的 消息模型更加丰富。
1.5 常见 MQ 产品
- ActiveMQ: 基于 JMS。
- RabbitMQ: 基于 AMQP,erlang 语言开发,稳定性好;
- RocketMQ: 基于 JMS,阿里巴巴产品,目前交由 Apache 基金会;
- Kafka: 分布式消息系统,高吞吐量。
二、核心概念
RabbitMQ 的5大核心概念:
Exchange
:交换机Queue
:队列Connection
:连接Channel
:信道Virtual host
:虚拟主机
2.1 工作原理图
- 中间的
Broker
表示 RabbitMQ 服务,每个 Broker 里面至少有一个 Virtual host 虚拟主机; - 每个虚拟主机中有自己的
Exchange
交换机、Queue
队列,Exchange 与 Queue 通过Binding
绑定; Producer
和Consumer
通过Connection
来保持联系,然后在 Connection 的基础上建立若干Channel
信道,用来发送和接收消息;Connection
和Channel
类似电缆和光纤的关系,一对多。
2.2 Exchange 交换机
Exchange
是一个比较重要的概念,它是消息到达RabbitMQ的 第一站,主要负责 根据不同的分发规则将消息分发到不同的Queue,供订阅了相关Queue的消费者消费到指定的消息。
Exchange的4种类型:
direct
、fanout
、topic
、headers
。
1)路由键
Routing key
:也叫Binding Key
,路由键
。当我们创建好 Exchange 和 Queue 之后,需要 使用路由键将 Exchange 和 Queue 绑定起来。
生产者在向 Exchange 发送消息的时候,必须指定一个Routing key,然后Exchange接收到这条消息之后,会 解析Routing key,然后根据Exchange和Queue的绑定规则,将消息分发到符合规则的Queue中。
2)direct 直连交换机
直连交换机
:会将消息转发到指定Routing key的Queue上,Routing key的解析规则为精确匹配。也就是只有当producer发送的消息的Routing key与某个Binding key相等时,消息才会被分发到对应的Queue上。
3)fanout 广播交换机
广播交换机
:不处理Routing key,而是会 将发送给它的消息路由到所有与它绑定的Queue上。
4)topic 主题交换机
主题交换机
:会 根据 通配符 对Routing key进行匹配,只要Routing key满足某个通配符的条件,就会被路由到对应的Queue上。
通配符的匹配规则如下:
- Routing key必须是一串字符串,每个单词用“.”分隔;
#
:表示匹配一个或多个单词;*
:表示匹配一个单词。
例如:
*.123
能够匹配到abc.123
,但匹配不到abc.def.123
;#.123
既能够匹配到abc.123
,也能匹配到abc.def.123
。
5)headers 头交换机(不常用)
头交换机
:头交换机中,Exchange与Queue之间不再通过Binding key绑定,而是通过 Arguments 绑定。
2.4 Queue 队列
队列
:用于存放消息,满足LIFO(后进先出)
规则。,生产者发送的消息会被放到 Queue 中,消费者消费消息时也是从 Queue 中取走消息。
2.5 Connection 连接
Connection 连接
:每个生产者和消费者要通过 RabbitMQ 发送与消费消息,首先就要 与 RabbitMQ 建立连接,这个连接就是Connection。- Connection是一个 TCP长连接。
2.6 Channel 信道
Channel 信道
:是 在Connection的基础上建立的虚拟连接,RabbitMQ中大部分的操作都是使用Channel完成的,比如:声明Queue、声明Exchange、发布消息、消费消息等。
你是否有这样一个疑问:既然已经有了Connection,我们完全可以使用Connection完成Channel的工作,为什么还要引入Channel这样一个虚拟连接的概念呢?
因为现在的程序都是支持多线程的,如果没有Channel,那么每个线程在访问RabbitMQ时都要建立一个Connection这样的TCP连接,对于操作系统来说,建立和销毁TCP连接是非常大的开销,在系统访问流量高峰时,会严重影响系统性能。
Channel就是为了解决这种问题,通常情况下,每个线程创建单独的Channel进行通讯,每个Channel都有自己的channel id帮助Broker和客户端识别Channel,所以Channel之间是完全隔离的。
2.7 Virtual host 虚拟主机
Virtual host 虚拟主机
:一个Broker中可以有多个Virtual host,每个Virtual host都有一套自己的Exchange和Queue。同一个Virtual host中的Exchange和Queue不能重名,不同的Virtual host中的Exchange和Queue名字可以一样。
这样,不同的用户在访问同一个RabbitMQ Broker时,可以创建自己单独的Virtual host,然后在自己的Virtual host中创建Exchange和Queue,很好地 做到了不同用户之间相互隔离的效果。
参考地址:
- RabbitMQ的工作模式及原理,https://baijiahao.baidu.com/s?id=1732891548341088166&wfr=spider&for=pc
2.RabbitMQ快速入门(详细),https://blog.csdn.net/kavito/article/details/91403659